I have a question about how to update a number field in Cloud Firestore. I followed an official document and it was not that hard to write code. But it didn't work as I wanted. It seems like I didn't use async and await properly. I haven't perfectly understood async and await now, so no idea where I missed.
GoodBad.jsx
import { useState } from 'react';
import { FaHeart, FaRegHeart } from 'react-icons/fa';
// import { FaThumbsUp, FaRegThumbsUp } from "react-icons/fa";
import {updateDoc, getDoc, doc } from 'firebase/firestore';
import db from '../config/firebase';
const GoodBad = ({ quiz }) => {
const [goodClicked, setGoodClicked] = useState(false);
const [goodCounter, setGoodCounter] = useState(quiz.likes);
// console.log(quiz.id, quiz.likes)
const handleLikesUI = async (e) => {
if (goodClicked === false) {
setGoodClicked(true);
setGoodCounter(prevState => prevState 1);
} else {
setGoodClicked(false);
setGoodCounter(prevState => prevState - 1);
}
const docRef = doc(db, "quizzes", quiz.id)
const payload = {likes: goodCounter}
await updateDoc(docRef, payload);
};
return (
<div className='quizFooter'>
<div
className={
goodClicked
? 'likesCounterContainer checked'
: 'likesCounterContainer'
}
onClick={() => handleLikesUI(quiz)}
>
<span className='heartIcon'>
{goodClicked ? <FaHeart /> : <FaRegHeart />}{' '}
</span>
<span className='likesNumber'>{goodCounter}</span>
{/* <span onClick={handleDislikes}>{goodClicked ? <FontAwesomeIcon icon="fa-regular fa-thumbs-down" /> : <FontAwesomeIcon icon="fa-solid fa-thumbs-down" />}bad: {badCounter}, {badClicked}</span> */}
</div>
</div>
);
};
export default GoodBad;
CodePudding user response:
I would suggest using useEffect()
for your use-case.
useEffect(() => {
const payload = {likes: goodCounter}
updateDoc(docRef, payload)
}, [goodCounter]);
const handleLikesUI = async (e) => {
if (goodClicked === false) {
setGoodClicked(true);
setGoodCounter(prevState => prevState 1);
} else {
setGoodClicked(false);
setGoodCounter(prevState => prevState - 1);
}
};
On the code above, this will listen to changes of goodCounter
in realtime and if there's change on the value of goodCounter
, it will now proceed updating your document. If you wont use useEffect, there will be a delay when setting setGoodCounter
.
As @mocherfaoui stated, if you want to just increment(or decrement) the existing value of a field, you must use increment
. See sample code below:
if (goodClicked) {
const n = 1
} else {
const n = -1
}
updateDoc(docRef, {
// `n` would be the number of increments (1 or -1).
likes: increment(n)
});
For more information, you may check this documentation.