I am wondering if there is a way to get around this: So, I am building a blog application using node.js, Mongodb and react.js. I added comment feature and I added reply to comments feature. Everything works well so far. My challenge is that I am using populate() method of mongodb which deals with ref id. Comment model has an array of replies that is referencing reply model. Everything is working well as I tested in postman. The challenge is implementing this in reactjs. I want to be able to delete each reply. I already implemented the update feature in react, but the delete feature needs two ids. That is what I don't know how to get. My route path is like this in node.js:
router.delete("/posts/:id/comments/:commentId/reply/:replyId", async (req, res) =>{
//my codes here
}
As you can see, I have post id, commentId and replyId. It is easy to copy and paste them in postman and test your logic. But it is a bit tricky with react.js.
I have a comment component where I rendered the comments array via map() method. You know, each has an array of replies. So, I mapped the replies as well. Now, to delete any reply, I need the post id, comment id and reply id. How do I get the comment id since the delete button is coming from the replies array? I can only fetch the replies id, but can't fetch the comment id. Have a look at my react code setup.
comments is the array of comments and in it, you have replies. Replies is an array of replies. I have to map into replies to display each replies.
return (
<div className="comment">
<h5 className='users-comment'>Users comments</h5>
{comments.map((singleComment, index)=>{
// console.log(singleComment)
const {author, commentdescription, _id, createdAt, replies} = singleComment
return(
<div className='displayed-comments'key={_id}>
<p className="comment-content"> {singleComment.commentdescription}</p>
</div>
)
//replies are returned here
{replies.map((singleReply) =>{
const {_id, author, createdAt, replycomment} = singleReply
return(
<div className='comment-div' key={_id} >
<i className={isLoading? "cursor-not-allowed singlePostIcon far fa-trash-alt":"singlePostIcon far fa-trash-alt" }
onClick={()=> handleDeleteComment(_id)}
></i>
<p className="comment-content">{replycomment}</p>
</div>
)
handleDeleteComment(_id) is a delete button that grabbed the id of the replies array individually. But to delete each replies, I need also need the id coming from the comments array that I mapped before the replies array.
Here is my delete logic in react:
//handle delete reply commmet
const handleDeleteComment = async (id)=>{
try{
await axios.delete(`/posts/${path}/comments/${id}/reply${id}`, {data: {author: user._id}});
window.location.replace("/")
}catch(err){
}
}
I have the post id known as ${path}, I have the reply id but the specific comment id is what I can't seem to get. Please, any help will be appreciated.
CodePudding user response:
- In your
handleDeleteComment
, pass two arguments instead of one,comment_id
andreply_id
.
//handle delete reply commmet
const handleDeleteComment = async (comment_id, reply_id) => {
try{
await axios.delete(`/posts/${path}/comments/${comment_id}/reply/${reply_id}`, {data: {author: user._id}});
history.replace("/") // See the next point
} catch(err){
}
}
- Use
history.replace("/")
instead ofwindow.location.replace("/")
because the former navigates to the new page without making a new HTTP call to the server where as the latter does that.
// imports
import { useHistory } from "react-router-dom"
...
function MyComponent(props){
// Creating the history object
const history = useHistory();
// Other Component logic
}
- On destructuring
singleComment
, do this instead
const {author, commentdescription, _id: comment_id, createdAt, replies} = singleComment
Now you have comment_id
for comment
and _id
for the reply. Just call your handleDelete
function as
onClick={()=> handleDeleteComment(comment_id, _id)}