How do I give a rating for a single post but not have to refetch all the posts.
Currently I have an array of posts that I map through. I am giving a rating for one post but have to refetch all the posts each time. Is there a way to only refetch the post I am giving the rating for?
On the Frontend I have:
const [posts, setPosts] = useState([])
useEffect(() => {
allPosts()
}, [])
const allPosts = async () => {
try {
const { data } = await axios.get(`/posts/${page}`)
setPosts(data)
} catch (err) {
console.log(err)
}
}
const likePost = async (e, newValue) => {
e.preventDefault()
setValue1(newValue)
try {
const { data } = await axios.put('/like-post', {
likeId: currentPost._id,
hover,
})
} catch (err) {
console.log(err)
}
}
In the Backend I am collecting all the posts:
export const posts = async (req, res) => {
try {
const currentPage = req.params.page || 1
const perPage = 5
const posts = await Post.find()
.skip((currentPage - 1) * perPage)
.limit(perPage)
.populate('postedBy')
.populate('comments.postedBy', '_id name image')
.sort({ createdAt: -1 })
res.json(posts)
} catch (err) {
console.log(err)
}
}
To Like the Post on the Frontend I am:
const [value1, setValue1] = useState(0)
const likePost = async (e, newValue) => {
e.preventDefault()
setValue1(newValue)
try {
const { data } = await axios.put('/like-post', {
likeId: currentPost._id,
hover,
})
allPosts()
} catch (err) {
console.log(err)
}
}
And to like on the Backend:
export const likePost = async (req, res) => {
try {
const { likeId, hover } = req.body
const user = await User.findById(req.user._id).exec()
const post = await Post.findById(likeId).exec()
// console.log(user.id)
let existingRatingObject = post.likes.find((ele) => ele.postedBy == user.id)
if (existingRatingObject === undefined) {
let ratingAdded = await Post.findByIdAndUpdate(
likeId,
{
$push: { likes: { starValue: hover, postedBy: user } },
},
{ new: true },
).exec()
res.json(ratingAdded)
} else {
// if user have already left rating, update it
const ratingUpdated = await Post.updateOne(
{ likes: { $elemMatch: existingRatingObject } },
{ $set: { 'likes.$.starValue': hover } },
{ new: true },
).exec()
res.json(ratingUpdated)
}
} catch (err) {
console.log(err)
}
}
2
Answers
Below is my JSX. I map posts to post and inside the post component I have a loadLikes, showAverage function and likePost.
Then I have the following functions:
I have added the oldData code in like you suggested, but this doesnt rerender the mapped post prop? not sure what I can do to update this?
@Ipizzinidev
If you want to trigger re-render you could declare the
likePost
function in the parent component and pass it to thePost
component as a prop.Doing this, you will be able to access the
setPosts
method and trigger re-render.In the parent component:
Then, change your
Post
component declaration to and remove thelikePost
function implementation from it:The
onChange
method definition on theRating
component will remain unchanged: