Wednesday, June 5, 2024
 Popular · Latest · Hot · Upcoming
147
rated 0 times [  154] [ 7]  / answers: 1 / hits: 11140  / 5 Years ago, thu, december 19, 2019, 12:00:00

I'm trying to use React hooks (useState & useEffect) in a component to show a vote count. After the user clicks up/down the 'vote' state should be increment or decremented and then the app makes an API call to PATCH the votes count in the database. The original vote count is coming from props passed from the parent component. But for some reason, the initial state for the votes is always 0 -- even though when I console.log the props it shows the correct number of votes?



PATCH request seems to be working fine, but something with hooks I think is wrong. Thanks in advance for any help I can get on this!





export default function Votes(props) {
const { item, voteCount, itemType } = props
const [votes, setVotes] = useState(voteCount || 0)

useEffect(() => {
if (itemType == 'question') {
questionApiService.updateQuestionFields({
questionId: item.id,
questionFields : { votes: `${votes}` }
})
} else if (itemType === 'answer') {
console.log('answer')
// questionApiService.updateAnswerFields({
// answerId: item.id,
// answerFields: { votes: votes }
//})
}
}, [votes])

const handleClick = e => {
e.currentTarget.id === increment
? setVotes(prevCount => prevCount + 1)
: setVotes(prevCount => prevCount - 1)
}

return (
<div className=QuestionPage__votes-count>
<button id=increment onClick={handleClick}>
<FontAwesomeIcon icon={faCaretUp} size=2x />
</button>
{votes}
<button id=decrement onClick={handleClick}>
<FontAwesomeIcon icon={faCaretDown} size=2x />
</button>
</div>
)
}




More From » reactjs

 Answers
13

You need to add itemType to the dependencies of useEffect, since you can't expect the prop to be available on the very first render, or to remain static throughout the component lifecycle. With your current example, the itemType referenced will always refer to its value at the very first time this function was run.



Also as others have mentioned, setting state initial value from props is a no-no. You can solve this by using a separate Effect to set state once your component receives its props:



...
const [votes, setVotes] = useState(0);
...

useEffect(() => {
setVotes(voteCount);
}, [voteCount]);

[#5285] Tuesday, December 17, 2019, 5 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
ammonderekm

Total Points: 247
Total Questions: 105
Total Answers: 98

Location: Tuvalu
Member since Sat, Feb 11, 2023
1 Year ago
ammonderekm questions
Tue, May 24, 22, 00:00, 2 Years ago
Wed, Mar 11, 20, 00:00, 4 Years ago
Thu, Oct 24, 19, 00:00, 5 Years ago
Wed, Jul 24, 19, 00:00, 5 Years ago
;