So I'm trying to implement a Comment System with React. (Non-interactive, just to render data). I'm having trouble with how to display the replies of each comment in the view.
comments.js (exports all the comment data)
const comments = [
{
....metadata, // this is where all the metadata for the comment goes, such as the content
replies: [
{
...metadata,
replies: [
// ...zero or more replies, of the same shape as comments[0]
]
}
]
},
// ...other comments, of the same shape as comments[0]
export default comments
comment.jsx (the functional component that each element of the comments
array above (and the replies
of each element) is passed into):
const Comment = props => (
<div>
<div>
{/* this is where all the comment's metadata will be rendered into */}
</div>
<div>{props.replies}</div>
</div>
)
export default comment
App.jsx (what is going to end up being rendered into the DOM)
import comments from "./comments.js"
import Comment from "./comment.jsx"
const App = () => (
{comments.map(comment => (
<Comment
{...comment.metadata,
replies:{comment.replies.map(reply => (
<Comment {...reply.metadata} />
))}
}
/>
))
}
)
The problem with my approach is that replies
that are buried more than 1 level deep from the topmost comment (ie replies
of replies
), won't be rendered into the DOM.
Can anyone please provide a way of rendering all the replies, down to the innermost reply?
Thank you!
CodePudding user response:
please check the following
There is a comment component which loops recursively,
import React, { useState } from 'react';
const Comment = ({ msg }) => {
return <div>{msg}</div>;
};
export default function App() {
const [comments] = useState([
{ msg: 'Lorem ipsum 1', replies: [{ msg: 'Lorem 1.1', replies:[{msg: 'Lorem 1.1.1'}] }] },
{ msg: 'Lorem ipsum 2' },
{ msg: 'Lorem ipsum 3', replies: [{ msg: 'Lorem 3.1' }] },
]);
const renderEl = (commentsData) => {
return (
<>
{
commentsData.map((r, k) => (
<div style={{ marginLeft: '3%' }} key={k}>
<Comment msg={r.msg} />
{r.replies && r.replies.length > 0 ? renderEl(r.replies, 0) : null}
</div>
))
}
</>
);
};
return renderEl(comments);
}
CodePudding user response:
You can use recursion to generate n-level nesting.
const createComment = (comments) => (
<>
{comments.map((comment) => (
<div key={comment.id}>
<div>{props.text}</div>
{comment.replies && comment.replies.map(rp => (createComment(rp.replies))}
</div>
))}
</>
);
export default function App() {
const comments = [{
id: 1,
text: "This is a comment",
replies: [
{
id: 2,
text: "This is a reply",
replies: [
{
id: 3,
text: "This is a reply",
replies: [],
},
],
},
],
}];
return (
<div className="App">
{createComment(comments)}
</div>
)
}