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
.