0

I have coded a simple React application that tracks feedback, the whole code for the application is below:

import React, { useState } from 'react'
import ReactDOM from 'react-dom'

const App = () => {
  // save clicks of each button to its own state
  const [good, setGood] = useState(0)
  const [neutral, setNeutral] = useState(0)
  const [bad, setBad] = useState(0)
  const [all, setAll] = useState(0)
  const [average, setAverage] = useState(0)
  const [positive, setPositive] = useState(0)


  const handleGood = () => {
    setGood(good + 1)
    setAll(all + 1)
    setAverage((average + 1) /(all))
    setPositive(good/all)
  }

  const handleNeutral = () => {
    setNeutral(neutral + 1)
    setAll(all + 1)
    setAverage((average) / (all))
  }

  const handleBad = () => {
    setBad(bad + 1)
    setAll(all + 1)
    setAverage((average - 1) / (all))
  }

  
  return (
    <div>
      <h1>give feedback</h1>
      <button onClick={handleGood}>good</button>
      <button onClick={handleNeutral}>neutral</button>
      <button onClick={handleBad}>bad</button>
      <h3>statistics</h3>

      <div>good {good}</div>
      <div>neutral {neutral}</div>
      <div>bad {bad}</div>
      <div>all {all}</div>
      <div>average {average}</div>
      <div>positive {positive}</div>


    </div>
  )
}

ReactDOM.render(<App />, 
  document.getElementById('root')
)

From the initial state if I click the "good" button once, the AVERAGE comes out to Infinity and POSTIVE comes out to Nan, I'm really confused why the application is behaving like this, is this because I'm using multiple setState methods in the click event handlers, and they are synchronous functions? Is there an important concept that I'm missing here when using useState hooks.

abdullahDev
  • 39
  • 1
  • 6
  • `setState` is **asynchronous** - the state won't be updated on the next line – Jayce444 Dec 04 '20 at 01:02
  • Does this answer your question? [useState set method not reflecting change immediately](https://stackoverflow.com/questions/54069253/usestate-set-method-not-reflecting-change-immediately) – Bergi Jan 19 '22 at 20:48

1 Answers1

2

and they are synchronous functions

Sort of - they don't return promises, but when you do:

setAll(all + 1)
setAverage((average) / (all))

all won't have updated until the next render cycle. What you need to do is more like:

const newAll = all + 1
setAll(newAll);
setAverage(average/newAll);

if you want to use the updated value immediately after setting it.

dave
  • 62,300
  • 5
  • 72
  • 93