I am trying to implement a feature in my project where I can like and unlike a post. I am working with NodeJs, Express, and MongoDB for back-end and ReactJs and axios on front-end The problem is that my DB is updating real-time when I hit the like/unlike button but on front-end, it's one render behind. Bellow you have some snippets of my code:
NodeJS
exports.likePost = catchAsync(async (req, res, next) => {
const post = await Post.findByIdAndUpdate(
req.params.id,
{
$push: { likes: req.user._id },
},
{
new: true,
}
);
if (!post) {
return next(new AppError('No post found with that ID', 404));
}
res.status(200).json({
status: 'success',
data: {
post,
},
});
});
exports.unlikePost = catchAsync(async (req, res, next) => {
const post = await Post.findByIdAndUpdate(
req.params.id,
{
$pull: { likes: req.user._id },
},
{
new: true,
}
);
if (!post) {
return next(new AppError('No post found with that ID', 404));
}
res.status(200).json({
status: 'success',
data: {
post,
},
});
});
Context State
const initialState = {
user: null,
currentPost: null,
posts: null,
trending: null,
newest: null,
error: null,
currentPostLiked: null,
};
const likePost = async (postId) => {
try {
const res = await axios.patch(`/api/v1/posts/${postId}/like`, null, {
headers: { Authorization: 'Bearer ' + localStorage.getItem('token') },
});
dispatch({
type: LIKE_POST,
// payload: res.data.data.post.likes,
});
} catch (err) {
console.log(err);
}
};
const unlikePost = async (postId) => {
try {
const res = await axios.patch(`/api/v1/posts/${postId}/unlike`, null, {
headers: { Authorization: 'Bearer ' + localStorage.getItem('token') },
});
dispatch({
type: UNLIKE_POST,
});
} catch (err) {
console.log(err);
}
};
Context Reducer
case LIKE_POST:
return {
...state,
currentPostLiked: true,
};
case UNLIKE_POST:
return {
...state,
currentPostLiked: false,
};
POST COMPONENT
const PostItem = ({ post }) => {
let currentPost = post;
const authContext = useContext(AuthContext);
const postContext = useContext(PostContext);
const { currentUser } = authContext;
const { likePost, unlikePost, currentPostLiked } = postContext;
const [liked, setliked] = useState(false);
useEffect(async () => {
if (currentUser) {
const currentLiked = post.likes.includes(currentUser.id);
if (currentLiked) {
const likedPost = await axios.get(`/api/v1/posts/${post.id}`);
currentPost = likedPost.data.data.post;
console.log('LIKED POST', likedPost);
// setliked(true);
}
if (!currentLiked) {
const likedPost = await axios.get(`/api/v1/posts/${post.id}`);
currentPost = likedPost.data.data.post;
console.log('UNLIKED POST', likedPost);
// setliked(false);
}
}
}, [currentPostLiked]);
const onLikePost = () => {
if (liked) {
unlikePost(post.id);
setliked(false);
}
if (!liked) {
likePost(post.id);
setliked(true);
}
};
const likeUnlike = liked ? 'fas fa-heart' : 'far fa-heart';
return (
<Likes onClick={onLikePost}>
<i className={likeUnlike} /> {currentPost.likes.length}
</Likes>
)
I have to let you know that I am a beginner and it might be a small logical mistake but I cannot figure it out, and the code looks a bit messy because I was trying a lot of approaches. Thank you guys for your time