2

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
  • 15,542
  • 12
  • 36
  • 40
  • 2
    Is your question about styling or about filtering? Are you asking how to separate the array into two lists? – Brian Thompson Nov 25 '20 at 16:51
  • @BrianThompson I want to display any comment reply with a margin to the left side just under it's main comment just like youtube comments . – Maxwell Fisher Nov 25 '20 at 16:55
  • Why does every comment have a `responseTo` property? And why don't you have comments with `id` 9 and 10 if you have these ids in `responseTo`s? – Zsolt Meszaros Nov 25 '20 at 17:07

1 Answers1

2

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
  • 15,542
  • 12
  • 36
  • 40