尝试递归呈现评论 ReactJs
Trying to recursively render comments ReactJs
这是我的评论数据结构。我想我有错误的数据结构来递归地呈现评论。请指教。我可以得到一个评论和一个回复,但不是未知数量的回复。
"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: 3,
content: "this is a comment",
replies: [
{
id: 1,
content: "This is a reply"
}
]
或者您可以将回复存储在与评论相同的级别。如果您选择此方法,您将需要一个 reply_to 属性,如果它是回复,它应该引用评论 ID,如果它是直接评论而不是评论,则应该引用 null(或者最好只是取消设置)回复。
您选择哪种方法取决于您的其余数据结构和应用程序行为。
假设您从 API 获得的数据结构是固定不变的,您可以从该平面数据中“膨胀”一棵评论树。我省略了下面的 user-id 和日期信息以缩短内容。
想法是 <CommentBoxes>
将评论列表呈现为 <CommentBox>
组件;传递完整的评论列表以确保 <CommentBox>
可以过滤它以找到它正在呈现的评论的子评论(如果有的话)。
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>
这是我的评论数据结构。我想我有错误的数据结构来递归地呈现评论。请指教。我可以得到一个评论和一个回复,但不是未知数量的回复。
"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: 3,
content: "this is a comment",
replies: [
{
id: 1,
content: "This is a reply"
}
]
或者您可以将回复存储在与评论相同的级别。如果您选择此方法,您将需要一个 reply_to 属性,如果它是回复,它应该引用评论 ID,如果它是直接评论而不是评论,则应该引用 null(或者最好只是取消设置)回复。
您选择哪种方法取决于您的其余数据结构和应用程序行为。
假设您从 API 获得的数据结构是固定不变的,您可以从该平面数据中“膨胀”一棵评论树。我省略了下面的 user-id 和日期信息以缩短内容。
想法是 <CommentBoxes>
将评论列表呈现为 <CommentBox>
组件;传递完整的评论列表以确保 <CommentBox>
可以过滤它以找到它正在呈现的评论的子评论(如果有的话)。
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>