DEV Community

Cover image for Building a Nested Comment App like Reddit
vigneshiyergithub
vigneshiyergithub

Posted on

11 2

Building a Nested Comment App like Reddit

What is this post about ?

Hello fellow humanoids. Today we will try to implement a basic nested comments component in React Js. This post won't be focused much on the styling rather the bare minimum logic required.

Check out the app here : Nested Comment

Nested comment app

Content

  • How to structure a comment
  • How to fetch all comments
  • React Comment component
  • Adding new comment

Lets go deep dive into each one and explore how it was implemented.

How to structure a comment

For this implementation we would be using flat structure to store all comments. This way fetching comment based on ID will be quicker.

const getNewComment = (commentValue, isRootNode = false, parentNodeId) => {
return {
id: uuidv4(),
commentText: commentValue,
childCommments: [],
isRootNode,
parentNodeId,
};
};

comments = {
  id1 : comment1,
  id2 : comment2
}
Enter fullscreen mode Exit fullscreen mode

How to fetch all comments

In this case we would enhance the existing comments from flat structure to nested structure so it can be used to render nested comments.

const commentMapper = (comment) => {
return {
...comment,
childCommments: comment.childCommments
.map((id) => comments[id])
.map((comment) => commentMapper(comment)),
};
};
const enhancedComments = Object.values(comments)
.filter((comment) => {
return !comment.parentNodeId;
})
.map(commentMapper);

React Comment component

Let's create a basic comment component with basic utility functions

const Comment = ({ comment, addComment }) => {
const { commentText, childCommments, id } = comment;
const [childComment, setChildComment] = useState("");
const [show, setShow] = useState(true);
const [showAddComponet, setShowAddComponet] = useState(false);
const onAdd = () => {
addComment(id, childComment);
setChildComment("");
setShowAddComponet(false);
};
return (
<div className="Comment">
<div
style={{
display: "flex",
flexDirection: "row",
justifyContent: "space-between",
}}
>
<div style={{ textAlign: "left" }}>{commentText}</div>
&nbsp;
{childCommments.length > 0 && (
<button onClick={() => setShow((show) => !show)}>
{show ? "Hide" : "Show"}
</button>
)}
</div>
<div>
<div>
{showAddComponet ? (
<>
<input
type="text"
value={childComment}
onChange={(e) => setChildComment(e.target.value)}
placeholder="add comment"
/>{" "}
<button onClick={onAdd}>Submit</button>
</>
) : (
<a
style={{ cursor: "pointer", fontSize: "0.7rem", color: "blue" }}
onClick={() => setShowAddComponet(true)}
>
Add a reply
</a>
)}
</div>
</div>
{show &&
childCommments.map((childCommentEl, key) => {
return (
<Comment
key={key}
comment={childCommentEl}
addComment={addComment}
/>
);
})}
</div>
);
};
view raw Comment.js hosted with ❤ by GitHub

Adding new comment

Once a new comment is added, based on the parentNodeId we can update the parent node and add a new comment to the comments list.

function App() {
const [comments, setComments] = useState(initialState);
const [rootComment, setRootComment] = useState("");
const addComment = (parentId, newCommentText) => {
let newComment = null;
if (parentId) {
newComment = getNewComment(newCommentText, false, parentId);
setComments((comments) => ({
...comments,
[parentId]: {
...comments[parentId],
childCommments: [...comments[parentId].childCommments, newComment.id],
},
}));
} else {
newComment = getNewComment(newCommentText, true, null);
}
setComments((comments) => ({ ...comments, [newComment.id]: newComment }));
};
const commentMapper = (comment) => {
return {
...comment,
childCommments: comment.childCommments
.map((id) => comments[id])
.map((comment) => commentMapper(comment)),
};
};
const enhancedComments = Object.values(comments)
.filter((comment) => {
return !comment.parentNodeId;
})
.map(commentMapper);
const onAdd = () => {
addComment(null, rootComment);
setRootComment("");
};
return (
<div className="App">
<header style={{marginBottom : '2rem', fontSize : '2rem'}}>Nested Comment Example</header>
<div className="comments-container">
<input
type="text"
value={rootComment}
onChange={(e) => setRootComment(e.target.value)}
placeholder="add comment"
style={{ width: "80%", marginRight: "1rem" }}
/>{" "}
<button onClick={onAdd}>Add</button>
</div>
<div
style={{
border: "1px solid blue",
width: "60%",
margin: "auto",
overflowX: "auto",
padding: "2rem",
}}
>
{enhancedComments.map((comment, key) => {
return (
<Comment key={key} comment={comment} addComment={addComment} />
);
})}
</div>
</div>
);
}
view raw Add comment.js hosted with ❤ by GitHub

Conclusion

This app was made as part of learning new components which are used in real life applications.
Stay safe and lend a hand to another :)

SurveyJS custom survey software

JavaScript UI Libraries for Surveys and Forms

SurveyJS lets you build a JSON-based form management system that integrates with any backend, giving you full control over your data and no user limits. Includes support for custom question types, skip logic, integrated CCS editor, PDF export, real-time analytics & more.

Learn more

Top comments (0)

SurveyJS custom survey software

JavaScript UI Libraries for Surveys and Forms

SurveyJS lets you build a JSON-based form management system that integrates with any backend, giving you full control over your data and no user limits. Includes support for custom question types, skip logic, integrated CCS editor, PDF export, real-time analytics & more.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay