Search code examples
reactjsfirebaseuse-statestate-managementconditional-rendering

How do I use like & unlike functionality on every element while using map to render those elements?


I have social media posts stored in firebase and each post has a like button. I am using map() function to render those posts but I have declared a single state for like button using useState(). When I click on like button in any of the posts, the state is getting changed for all the posts and same is happening when I dislike. How do I change the state for that particular post on which like is cliked??

function Feed(){

const [like, setLike] = useState(false);
const [heart, setHeart] = useState(false);
{posts.map((item) => (
      <div
        key={item.id}
        className=" flex flex-col gap-2 bg-white rounded-xl p-3 border border-gray-300 shadow- 
 lg mb-2"
      >
        <div className=" flex gap-2 items-center">
          <img
            src={userImage}
            className=" w-[48px] h-[48px] rounded-full "
            alt=""
          />
          <span className=" text-black font-semibold text-sm">
            {userName}
          </span>
        </div>
        <hr />
        {item.body && <p>{item.body}</p>}
        {item.imageUrl && <img src={item.imageUrl} alt="" />}
        {item.videoUrl && (
          <iframe
            src={item.videoUrl}
            title={item.id}
            frameBorder="0"
            className=" w-full h-[20rem] "
          ></iframe>
        )}

        <hr />
        <div className=" flex gap-2">
          {like ? (
            <ThumbUpIcon
              className=" cursor-pointer text-blue-600 hover:bg-gray-100 px-2 py-2 
   hover:rounded-md"
              fontSize="large"
              onClick={() => setLike(!like)}
            />
          ) : (
            <ThumbUpOutlinedIcon
              className=" cursor-pointer text-gary-500 hover:bg-gray-100 px-2 py-2 
   hover:rounded-md"
              fontSize="large"
              onClick={() => setLike(!like)}
            />
          )}
          {heart ? (
            <FavoriteOutlinedIcon
              className=" cursor-pointer text-red-500 hover:bg-gray-100 px-2 py-2 
   hover:rounded-md"
              fontSize="large"
              onClick={() => setHeart(!heart)}
            />
          ) : (
            <FavoriteBorderOutlinedIcon
              className=" cursor-pointer text-gary-500 hover:bg-gray-100 px-2 py-2 
    hover:rounded-md"
              fontSize="large"
              onClick={() => setHeart(!heart)}
            />
          )}
        </div>
      </div>
    ))}
   }

Solution

  • I suggest instead of a boolean variable for keeping like for posts, define an array and add the id of each element that liked

    const [likes, setLikes] = useState([]);
    
    And
    
    likes.findIndex(x=>x===item.id)<0 ?
    
    onClick={() => {likes.add(item.id);setLikse(...likes)}}
    
    

    Sandbox: Simple Sample is here