Как отображать ответы на комментарии с полями в react js?

#javascript #reactjs

#javascript #css #reactjs

Вопрос:

У меня есть comments объект, который имеет четыре значения:

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' }
];
 

Я хочу отображать ответы с полями слева (комментарии Джона и Тины). Комментарии Тины и Джона — это ответы Максу и Карлу.

App.js

 import { comments } from './data';

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

Как я могу отображать ответы на комментарии с полями слева?

Ответ №1:

Я бы, вероятно, изменил способ хранения ваших комментариев. Вы можете добавить ответы в виде массива в комментарий. Таким образом, вы также можете легко оформить комментарии и ответы.

Проверьте фрагмент ниже. Я создал Comment компонент, который проверяет, есть ли responseTo другой комментарий. Если это так, то это добавляет дополнительный класс.

 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 amp;amp;
        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>