Reputation: 689
Basically I have a nested comments by doing recursion.
Currently this is the behavior of the component
Before onclick :
How do I toggle component when I click on the button ?
Attached is my code
//data.js
const post = {
"post": {
"img": "",
"likes": [
"60c418582f7066090ced4a51"
],
"comments": [
{
"comments": [
{
"comments": [
{
"comments": [
{
"comments": [],
"_id": "60d6ab9207c0a573786a9e65",
"userId": "60c418582f7066090ced4a51",
"content": "good post 3",
"createdAt": "2021-06-26T04:22:42.337Z",
"updatedAt": "2021-06-26T04:22:42.337Z",
"__v": 0
}
],
"_id": "60d6962cee10aa73f820b974",
"userId": "60c418582f7066090ced4a51",
"content": "good post 2",
"createdAt": "2021-06-26T02:51:24.111Z",
"updatedAt": "2021-06-26T04:22:42.622Z",
"__v": 0
},
{
"comments": [],
"_id": "60d705784ab01c354cf7f445",
"userId": "60c15ac41ed8da1ab4efe7f3",
"content": "Comment deleted by User",
"createdAt": "2021-06-26T10:46:16.813Z",
"updatedAt": "2021-06-26T12:29:06.398Z",
"__v": 0
},
{
"comments": [],
"_id": "60d706febcba957b04406547",
"userId": "60c15ac41ed8da1ab4efe7f3",
"content": "yes it is a good post 1 from alexane Updated",
"createdAt": "2021-06-26T10:52:46.679Z",
"updatedAt": "2021-06-26T12:17:58.879Z",
"__v": 0
}
],
"_id": "60d695b4ee10aa73f820b973",
"userId": "60c418582f7066090ced4a51",
"content": "good post 1",
"createdAt": "2021-06-26T02:49:24.426Z",
"updatedAt": "2021-06-26T12:30:44.872Z",
"__v": 0
}
],
"_id": "60d68e32dff84439a4d3b191",
"userId": "60c418582f7066090ced4a51",
"content": "good post",
"createdAt": "2021-06-26T02:17:22.625Z",
"updatedAt": "2021-06-26T02:49:24.820Z",
"__v": 0
},
{
"comments": [
{
"comments": [],
"_id": "60d6c2d917d0b12be44742d2",
"userId": "60c418582f7066090ced4a51",
"content": "nice post 1",
"createdAt": "2021-06-26T06:02:01.420Z",
"updatedAt": "2021-06-26T06:02:01.420Z",
"__v": 0
}
],
"_id": "60d6bebf17d0b12be44742d1",
"userId": "60c418582f7066090ced4a51",
"content": "nice post",
"createdAt": "2021-06-26T05:44:31.436Z",
"updatedAt": "2021-06-26T06:02:01.676Z",
"__v": 0
},
{
"comments": [
{
"comments": [],
"_id": "60d87e7df43fed7e4079875e",
"userId": "60c15ac41ed8da1ab4efe7f3",
"content": "awesome post 1",
"createdAt": "2021-06-27T13:34:53.192Z",
"updatedAt": "2021-06-27T13:34:53.192Z",
"__v": 0
}
],
"_id": "60d87cb4f43fed7e4079875d",
"userId": "60c418582f7066090ced4a51",
"content": "awesome post",
"createdAt": "2021-06-27T13:27:16.299Z",
"updatedAt": "2021-06-27T13:34:53.468Z",
"__v": 0
}
],
"_id": "60c5a23eb37b425a00968fa9",
"userId": "60c418582f7066090ced4a51",
"description": "This is a sample Post 2",
"createdAt": "2021-06-13T06:14:22.196Z",
"updatedAt": "2021-06-27T13:27:16.577Z",
"__v": 0
},
"count": 10
}
export default post
//Comment.js
import post from './data'
const NestedComments = () => {
const [comments, setComments] = useState(post.post.comments);
return (<div className="commentDiv">
<div>
<span>Username</span>
</div>
<Comments
comments={comments}
/>
</div>)
}
const Comments = ({
comments,
}) => {
const [isClicked, setisClicked] = useState(false);
const [commentId, setcommentId] = useState(null);
const nestedComments = (comment) => {
return comment.comments ? (
<div className={`childCommentsof-${comment._id}`}>
<Comments
comments={comment.comments}
/>
</div>
) : null
}
const trigger = (e, id) => {
e.preventDefault()
if (e.target.className.baseVal === 'MuiSvgIcon-root') {
const targetId = e.target.parentElement.id
if (targetId === id) {
setisClicked(!isClicked)
setcommentId(id)
}
return
}
}
return (
<>
{
(comments || []).map(comment => {
return (
<ul key={comment._id} className={`commentsUL-${comment._id} commentsList`} >
<li>
<button className='customBtn' id={comment._id}>
{
(!isClicked || comment._id !== commentId) && <Remove onClick={(e) => trigger(e, comment._id)} />
}
{
isClicked === true && comment._id === commentId && <Add />
}
</button>
{comment.content}
<span><button>Reply</button></span>
</li>
{nestedComments(comment)}
</ul>
)
})
}
</>
)
}
Currently the behavior is when user clicks on a minus button , only one of the button gets Toggle and become a Plus button. What I would like to achieve is when user clicks on the minus button , it will become plus sign? The javascript way would be using the e.target and replace the element.
How can it be achieved using React? I am kinda stuck here for hours, any help would be very appreciated. Thank you.
Any help given will be appreciated. Thank you.
Upvotes: 0
Views: 87
Reputation: 613
You can simplify the logic of your trigger
function (or remove it altogether) by creating a single comment component which will have its own state. This makes it much simpler as you won’t be needing to check for id’s or anything.
If you need to add extra classes you can do by checking for isClicked
inside of <SingleComment />
.
Here is the final code — I refactored a bit to make it easier to maintain/read:
import React, { useState } from "react";
import post from "./data";
// Single comment
const SingleComment = ({ comment }) => {
const [isClicked, setIsClicked] = useState(false);
return (
<li>
<button className="customBtn" id={comment._id}>
{!isClicked && (
<Remove
onClick={(e) => {
setIsClicked(!isClicked);
// add your remove comment logic here
}}
/>
)}
{isClicked && <Add />}
</button>
{comment.content}
<span>
<button>Reply</button>
</span>
</li>
);
};
// Nested comments
const NestedComments = () => {
const [comments, setComments] = useState(post.post.comments);
return (
<div className="commentDiv">
<div>
<span>Username</span>
</div>
<Comments comments={comments} />
</div>
);
};
// Comment list
const Comments = ({ comments }) => (
<>
{(comments || []).map((comment) => (
<ul
key={comment._id}
className={`commentsUL-${comment._id} commentsList`}
>
<SingleComment comment={comment} />
{comment.comments && <NestedComments />}
</ul>
))}
</>
);
Upvotes: 1
Reputation: 2363
Okay, what you need to do is maintain a list of clicked comments inside your component.
const [clickedCommentIdList, setClickedCommentIdList] = useState([]);
now when you trigger you need to update the list like this
setClickedCommentIdList((prev) => [...prev, id]);
and finally inside your component check if the component is already checked or not
{!checkIfClicked(comment._id) ? (
<button onClick={(e) => trigger(e, comment._id)}>
remove
</button>
) : (
<button>Add</button>
)}
here is a working version fr you
https://codesandbox.io/s/happy-snow-dqbbc?file=/src/App.js:5031-5267
Upvotes: 1