【问题标题】:Trying to recursively render comments ReactJs尝试递归呈现评论 ReactJs
【发布时间】:2020-09-08 16:38:19
【问题描述】:

这是我的 cmets 的数据结构。我认为我有错误的数据结构来递归地渲染 cmets。请指教。我可以获得单个 cmets 和一个回复,但不能获得未知数量的回复。

  "comments": [
    {
      "id": 1,
      "content": "This is so great!",
      "recipe_id": 1,
      "commentable_id": 1,
      "commentable_type": "Recipe",
      "user_id": 1,
      "created_at": "2020-09-08T00:16:55.296Z",
      "updated_at": "2020-09-08T00:16:55.296Z"
    },
    {
      "id": 2,
      "content": "This is another one",
      "recipe_id": 1,
      "commentable_id": 1,
      "commentable_type": "Comment",
      "user_id": 1,
      "created_at": "2020-09-08T00:16:55.323Z",
      "updated_at": "2020-09-08T00:16:55.323Z"
    },
    {
      "id": 3,
      "content": "This is another one",
      "recipe_id": 1,
      "commentable_id": 2,
      "commentable_type": "Comment",
      "user_id": 1,
      "created_at": "2020-09-08T00:16:55.332Z",
      "updated_at": "2020-09-08T00:16:55.332Z"
    },

【问题讨论】:

  • ID 为 2 和 ID 为 3 的对象是 ID 为 1 的对象的子对象吗?也就是说,对于带有commentable_type == 'Comment' 的对象,commentable_id 指的是评论 ID?
  • @AKX 对象 ID 2 是 ID 1 的子对象,ID 3 是 ID2 的子对象。 Commentable_id 是指被评论的评论id。希望这能澄清一点

标签: reactjs rails-api


【解决方案1】:

假设您从 API 获得的数据结构是一成不变的,您可以从该平面数据“膨胀”一棵 cmets 树。我省略了下面的用户 ID 和日期信息以缩短内容。

这个想法是 <CommentBoxes> 将 cmets 列表呈现为 <CommentBox> 组件;传递完整的 cmets 列表,以确保 <CommentBox> 可以过滤它以查找子 cmets(如果有)以获取它正在呈现的评论。

const commentData = [
  {
    id: 1,
    content: "This is so great!",
    recipe_id: 1,
    commentable_id: 1,
    commentable_type: "Recipe",
  },
  {
    id: 2,
    content: "This is another one",
    recipe_id: 1,
    commentable_id: 1,
    commentable_type: "Comment",
  },
  {
    id: 3,
    content: "This is another one",
    recipe_id: 1,
    commentable_id: 2,
    commentable_type: "Comment",
  },
];

const CommentBox = ({ comment, allComments }) => {
  const children = allComments.filter(
    (c) => c.commentable_type === "Comment" && c.commentable_id === comment.id
  );
  return (
    <li>
      {comment.content}
      {children ? <CommentBoxes comments={children} allComments={allComments} /> : null}
    </li>
  );
};

const CommentBoxes = ({ comments, allComments }) => (
  <ul>
    {comments.map((c) => (
      <CommentBox comment={c} allComments={allComments} key={c.id} />
    ))}
  </ul>
);

const App = () => {
  const rootComments = commentData.filter((c) => c.commentable_type === "Recipe");
  return <CommentBoxes comments={rootComments} allComments={commentData} />;
};

ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.1/umd/react-dom.production.min.js"></script>
<div id="root"></div>

【讨论】:

  • 非常感谢!作为一个反应新手,这是非常有用的解释。我已经在我的应用程序中对其进行了测试,效果很好!很高兴看到未来如何解决类似挑战的思考过程。
  • 您是否知道我该如何处理每条评论的回复,然后提交该回复?我试图实现它,它只是无限循环和崩溃。非常感谢。
  • &lt;CommentBox&gt; 也渲染一个&lt;ReplyBox&gt; 怎么样(它本身不会渲染任何子CommentBoxes 或CommentBoxeses?
  • 我认为我误解了这个概念,如果我没有正确遵循您的建议,我深表歉意。我添加了``` ``` 到评论框
  • ,它不会让我在文本框中输入任何数据以进行回复。
  • 在不知道 replyupdateReply 是什么的情况下,这并没有多大帮助...请使用完整修改后的代码提出另一个问题,并可能在此处链接,以便我看看.
  • 【解决方案2】:

    有两种方法可以实现:

    您可以将回复存储为 cmets 的子项:

    {
      id: 3,
      content: "this is a comment",
      replies: [
        {
          id: 1,
          content: "This is a reply"
        }
    ]
    

    或者您可以将回复存储在与 cmets 相同的级别。如果您选择此方法,您将需要一个 reply_to 属性,如果它是一个回复,它应该引用一个评论 id,或者如果它是一个直接评论而不是一个回复,它应该引用一个 null(或者更好但只是未设置)。

    您选择哪种方法取决于您的其余数据结构和应用行为。

    【讨论】:

      猜你喜欢
      相关资源
      最近更新 更多
      热门标签