I cannot figure out for the life of me why the first pair of onDoubleClick
fires 500
server error but on all subsequent onDoubleClick
s, it fires 200
correctly but with inconsistent behavior depicted below.
For illustration purposes, this is what's happening:
- double click on image A for user ID
1
-> 500 error - double click on image A for user ID
1
-> 200 success (updates successfully for user ID1
) - double click on image B for user ID
2
-> 200 success (updates successfully for user ID1
when it should've been updated for user ID2
) - and so on....
I've checked all over SO, even tried all of the suggestions on the most popular question asked on this topic on SO but to no avail. I've hit a brick wall.
I believe it has something to do with the asynchronous nature of hooks and how I'm defining them but I'm not entirely sure.
How can I make it so that upon double clicking any image, the corresponding data gets sent to the server correctly on the first pair of double clicks as well as any subsequent pair double clicks (i.e. on a different image)?
For illustration purposes, this how I'd like it to behave:
- double click on image A for user ID
1
-> 200 success (updates successfully for user ID1
) - double click* on image b for user ID
2
-> 200 success (updates successfully for user ID2
) - and so on....
const Images = () => {
let authToken = localStorage.getItem("token");
const [uploadsData, setUploadsData] = useState([]);
const [likedPhotoUserId, setLikedPhotoUsedId] = useState("");
const [like, setLike] = useState(0);
useEffect(() => {
getUploads();
}, []);
useEffect(() => {}, [uploadsData]);
const getUploads = () => {
const headers = {
Accept: "application/json",
Authorization: `Bearer ${authToken}`,
};
axios
.get("http://localhost:8005/api/get-user-uploads-data", { headers })
.then((resp) => {
console.log(resp.data);
setUploadsData(resp.data);
})
.catch((error) => {
console.log(error);
});
};
const handleLikesBasedOnUserId = (e) => {
setLikedPhotoUsedId(e);
sendUserLikePost();
};
const sendUserLikePost = () => {
const url = "http://localhost:8005/api/post-user-like";
const headers = {
Accept: "application/json",
Authorization: `Bearer ${authToken}`,
};
let data = {
like: like,
UserID: likedPhotoUserId,
};
console.log(data);
axios
.post(url, data, { headers })
.then((resp) => {
console.log(resp.data);
})
.catch((error) => {
console.log(error);
});
};
const displayUploadsData = () => {
return uploadsData.map((photos, index) => {
return (
<ImagesGrid
src={photos.url}
likes={photos.likes}
userName={photos.name}
key={index}
doubleClick={handleLikesBasedOnUserId}
value={photos.UserID}
/>
);
});
};
return <>{displayUploadsData()}</>;
};
const ImagesGrid = (props) => {
const createUserPhotoNodes = () => {
return (
<section className="gallery">
<div className="container">
<form method="POST" name="likes">
<div className="img-container">
<img
src={props.src}
alt="Photo"
className="gallery-img"
onDoubleClick={() => props.doubleClick(props.value)}
/>
<h2 className="userName">{props.userName}</h2>
<h2 className="likes" onChange={props.onChange}>
Likes {props.likes}
</h2>
</div>
</form>
</div>
</section>
);
};
return <>{createUserPhotoNodes()}</>;
};
CodePudding user response:
You have hit the nail on the head – it's because setState
is asynchronous and you're seeing stale props or state to boot.
With
const handleLikesBasedOnUserId = (e) => {
setLikedPhotoUsedId(e);
sendUserLikePost();
};
const sendUserLikePost = () => {
// ...
let data = {
'like': like,
'UserID': likedPhotoUserId
};
// ...
likedPhotoUserId
will not have updated before you call sendUserLikePost
, so likedPhotoUserId
is ''
. (By the time you call handleLikes...
again it will have the "previous" value.)
I don't see a reason why likedPhotoUserId
should be a state atom anyway, since all you use it for is sendUserLikePost
– just make it a regular ol' parameter:
const handleLikesBasedOnUserId = (e) => {
sendUserLikePost(e);
};
const sendUserLikePost = (likedPhotoUserId) => {
// ...
let data = {
'like': like,
'UserID': likedPhotoUserId
};
// ...