Home > Enterprise >  React state adds 1 but subtracts 2
React state adds 1 but subtracts 2

Time:02-28

I am writing a function to like/unlike posts and add or subtract 1 from the likes total. Something isn't right as the addition works correctly (adds 1) but it subtracts 2 for some reason. I am not sure if it's to do with the state update delay.

const Post = (props: PostProps) => {
  const {
    post: {
      content,
      author,
      postedDate,
      likes,
      comments,
      shares,
      isLiked,
      isBookmarked,
    },
  } = props;

  const [isPostBookmarked, setIsPostBookmarked] = useState(isBookmarked);
  const [isPostLiked, setIsPostLiked] = useState(isLiked);
  const [likesCount, setLikesCount] = useState(likes);

  const handlePostLikeClick = () => {
    setIsPostLiked((prevIsLikedState) => {
      setLikesCount((prevLikesCountState) => {
        return prevIsLikedState
          ? prevLikesCountState - 1
          : prevLikesCountState   1;
      });

      return !prevIsLikedState;
    });

    return (
      <IconButton
        icon={Heart}
        label={likesCount}
        filled={isPostLiked}
        onClick={handlePostLikeClick}
      />
    )
  };

CodePudding user response:

You are nesting two different state updates in same function which leads to some fuzzy issues,

Can you try changing you handlePostLikeClick function to the one mentioned below??

  const handlePostLikeClick = () => {
    setLikesCount((prevLikesCountState) => {
      return isPostLiked ? prevLikesCountState - 1 : prevLikesCountState   1;
    });
    setIsPostLiked((prevIsLikedState) => {
      return !prevIsLikedState;
    });
  };

You can use this code sandbox for reference

CodePudding user response:

The answer given by @sumanth seems quite right, but it seems something missing. In the given answer, using same onClick function handlePostLikeClick, 2 states are going to be updated. But it should only be used to update isPostLiked. Because likesCount should be updated only if any state changes detected for isPostLiked state. Therefore, it is essential to use use effect as follows.

  const [isPostLiked, setIsPostLiked] = useState(false);
  const [likesCount, setLikesCount] = useState(1);

  useEffect(() => {
    setLikesCount((current) => (isPostLiked ? current   1 : current - 1));
  }, [isPostLiked]);

  const handlePostLikeClick = () => {
    setIsPostLiked((prevIsLikedState) => !prevIsLikedState);
  };

Explantion

Initial state for likesCount used as 1, because during initial rendering use effect will be triggered and update likesCount to 0 (since isPostLiked initial state is false). Additionally, you can see likesCount increases its count only if isPostLiked is true.

But with @sumaneth answer, likesCount increases if isPostLiked is false.

isPostLiked ? prevLikesCountState - 1 : prevLikesCountState   1;

Therefore, it's not tracking current change of isPostLiked state, but it's using its previous state to do the update on likesCount.

Therefore, you defenitely, need to use use effect to keep track on the current change of isPostLiked state and do the update on likesCount.

  • Related