3

I have a comments object that has four values:

data.js

export const comments = [
    { id: 1, content: 'comment 1', responseTo: 9, writer: 'Max' },
    { id: 2, content: 'comment 2', responseTo: 1, writer: 'John' },
    { id: 3, content: 'comment 2', responseTo: 1, writer: 'John' },
    { id: 4, content: 'comment 2', responseTo: 1, writer: 'John' },
    { id: 6, content: 'comment 3', responseTo: 10, writer: 'Karl' },
    { id: 7, content: 'comment 4', responseTo: 6, writer: 'Tina' },
    { id: 8, content: 'comment 4', responseTo: 6, writer: 'Tina' }
];

I want to display the replies with a margin on the left (John and Tina comments). Tina and John comments are replies to Max and Karl.

App.js

import { comments } from './data';

function App() {
    return (
        <div>
            {comments.map((each) => {
                return (
                        <Fragment>
                            <Comment each={each} />
                        </Fragment>
                    )
                );
            })}
        </div>
    );
}

How can I display the comment replies with a margin on the left ?

Zsolt Meszaros
  • 21,961
  • 19
  • 54
  • 57

1 Answers1

3

I'd probably change how your comments are stored. You can add the replies as an array on the comment. This way you can easily style the comments and replies too.

Check the snippet below. I've created a Comment component, which checks if is a responseTo other comment. If it is, it adds an extra class.

function Comment({ comment }) {
  return (
    <div
      key={comment.id}
      className={comment.responseTo ? "comment comment--reply" : "comment"}
    >
      <a href={`/user/${comment.writer}`}>{comment.writer}</a>
      <p>{comment.content}</p>
      {comment.responses &&
        comment.responses.map((reply) => (
          <Comment key={reply.id} comment={reply} />
        ))}
    </div>
  );
}

function getThreadedComments(data) {
  const comments = [];

  for (let comment of data) {
    if (comment.responseTo) {
      const index = comments.findIndex((i) => i.id === comment.responseTo);
      comments[index].responses.push(comment);
    } else {
      comments.push({ ...comment, responses: [] });
    }
  }

  return comments;
}

function App() {
  const data = [
    { 
      id: 1,
      content: "comment 1",
      responseTo: null,
      writer: "Max"
    },
    {
      id: 2,
      content: "comment #2, in response to Max",
      responseTo: 1,
      writer: "John"
    },
    { 
      id: 3,
      content: "Max, that's great!",
      responseTo: 1,
      writer: "Peter"
    },
    {
      id: 4,
      content: "Okay, it's really impressive ;)",
      responseTo: 1,
      writer: "Vic"
    },
    { 
      id: 5,
      content: "Great content!",
      responseTo: null,
      writer: "Lilly"
    },
    {
      id: 6,
      content: "comment 3",
      responseTo: null,
      writer: "Karl"
    },
    {
      id: 7,
      content: "Oi, Karl! This is comment 7",
      responseTo: 6,
      writer: "Tina"
    },
    { 
      id: 8,
      content: "@Karl, just do not...",
      responseTo: 6,
      writer: "Chris"
    }
  ];
  const comments = getThreadedComments(data);

  return (
    <div className="App">
      <h2>Comments</h2>
      {comments.map((comment) => (
        <Comment key={comment.id} comment={comment} />
      ))}
    </div>
  );
}

ReactDOM.render(<App />, document.getElementById('root'));
body {
  color: #353635;
  font-family: sans-serif;
  line-height: 1.5;
}

a {
  color: #1979c9;
  text-decoration: none;
}

.comment {
  border-left: 4px solid rgba(0, 0, 0, 0.1);
  margin-bottom: 1rem;
  padding: 0.5rem 1rem;
}

.comment--reply {
  margin-left: 0.5rem;
}
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
Zsolt Meszaros
  • 21,961
  • 19
  • 54
  • 57