desh
desh

Reputation: 689

Toggle Elements during onClick

Basically I have a nested comments by doing recursion.

Currently this is the behavior of the component

Before onclick :

enter image description here

After onclick: enter image description here

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

Answers (2)

Edmundo Santos
Edmundo Santos

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

Mohammad Faisal
Mohammad Faisal

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

Related Questions