Newbie here. Trying to learn React and I am currently trying to display the average=(good+bad)/all
However, I keep getting NaN which I am assuming I am getting because my state values are all 0. I am confused as to why this is because after calling setClicks(newStats) I thought the stats are updated.
import React, { useState } from "react"
const App = () =>{
const [stats,setClicks] = useState({good:0,neutral:0,bad:0,all:0,positive:0,average:0})
const handleGood=()=>
{
const newStats={
...stats,
all: stats.all +1,
good:stats.good +1,
average: (stats.good - stats.bad)/stats.all,
}
setClicks(newStats)
console.log("Stats.good",stats.good)
console.log("Stats.bad",newStats.bad)
console.log("Stats.all",stats.all)
}
const handleBad=()=>
{
const newStats= {
...stats,
bad: stats.bad+1,
all: stats.all+1,
average: (stats.good - stats.bad)/stats.all,
}
setClicks(newStats)
}
const handleNeutral =() =>
{
const newStats={
...stats,
neutral:stats.neutral +1,
all: stats.all+1,
average: (stats.good - stats.bad)/stats.all,
}
setClicks(newStats)
}
const Button =({handleClick,text})=>{
return(
<button onClick={handleClick}>{text}</button> )
}
return(
<div>
<h1>Give Feedback</h1>
<Button handleClick={handleGood} text="good"/>
<Button handleClick={handleNeutral} text="neutral"/>
<Button handleClick={handleBad} text="bad"/>
<br/>
<h2>Statistics</h2>
<p>good: {stats.good}</p>
<p>neutral: {stats.neutral}</p>
<p>bad: {stats.bad}</p>
<p>all:{stats.all}</p>
<p>average: {stats.average}</p>
<p>positive: {stats.positive}</p>
</div>
)
}
export default App
What is the best way to change state? How should this be done so NaN does not appear?
For the initial calculation of average, you need to use the updated values:
const handleGood= () => {
const newAll = stats.all + 1;
const newGood = stats.good + 1;
const newStats={
...stats,
all: newAll ,
good:newGood ,
average: (newGood - stats.bad)/newAll,
}
setClicks(newStats);
}
You are getting NaN because you are dividing 0/0 and not calculating the average correctly. You should use new good, bad, ... values for average.
In this part of your code:
const newStats={
...stats,
all: stats.all +1,
good:stats.good +1,
average: (stats.good - stats.bad)/stats.all,
}
You are calculating average with the old values of all, good in your state.
By the way, adding Math.abs avoid getting a negative average value.
This is an updated version of your handleGood function.
const handleGood=()=>
{
const newAll = stats.all +1;
const newGood = stats.good +1;
const newAverage = Math.abs(newGood-stats.bad)/newGood
const newStats={
...stats,
all: newAll,
good:newGood,
average: newAverage,
}
setClicks(newStats)
console.log("Stats.good",newStats.good)
console.log("Stats.bad",newStats.bad)
console.log("Stats.all",newStats.all)
}