0

While trying to understand React hooks, i wrote this small code:

import React, {useState} from "react";
import "./styles.css";

export default function App(props) {
  var [x, setX] = useState(0);

  function handleClick(e) {
    setX(x++);

    console.log(x);
  }

  return(<div className="App">
    <h3 className="h"> Welcome user, please press this button:</h3>   
    {x}
    <br/>
    <button className='button' onClick={handleClick}> Click </button>
  </div>);
}

I was expecting to get output 1 2 3 4 5 6... in console whenever i press the button, but i got this weird output instead 1 2 2 3 3 4 4 5 5 6 6 .

Can someone explain why we get such output and how to fix it ?

Moody
  • 43
  • 1
  • 7
  • 1
    I have answered a similar question some time ago: https://stackoverflow.com/questions/59495222/cant-setstate-in-reactjs/59495252#59495252. Basically, setting of state is asynchronous, thats why logging the state right after `setX` might result in 'older' values. – wentjun May 03 '20 at 11:59
  • I don't see how you are getting duplicated values with only one `console.log` in your code like this - are you sure you can reproduce your problem with the code listed? (and yes, neither modifying `x` nor `console.log` after `setX` do not make sense, but those are separate problems that wouldn't duplicate the output) – Aprillion May 03 '20 at 12:06
  • I also don't know how i got duplicated values, but when i tried Antoni's answer, the problem was fixed ! I will now try to understand more what caused that behavior. – Moody May 03 '20 at 12:35

2 Answers2

1

You're modifying x with x++ command and then setting it again. You need to do something like this in the handleClick function:

setX(x + 1);

console.log(x);

The reason is that x++ is equivalent to x = x + 1 not x + 1.

Bonus tip:

Use const instead of var so that the interpreter warns you about modifying an immutable value.

  • it does not make sense to console.log after `setX` - https://stackoverflow.com/a/58877875/1176601 – Aprillion May 03 '20 at 12:03
  • yes, the `x` inside the `console.log` will print the previous value, you could save the `x+1` into a variable and print that, since `setX` is pretty much guaranteed to set the state – Antoni Silvestrovič May 03 '20 at 12:05
  • I just added console.log for debugging purpose, now i will delete it. – Moody May 03 '20 at 12:24
0

You can also pass a callback function to your setX function.

This will ensure, that while doing computations, you will always have the previous value within the callback.

This is because setX is an async function.

You can do like so :

  function handleClick(e) {
    setX(previousCount => previousCount + 1);
    console.log(x);
  }

Working implementation attached.

Edit friendly-minsky-839d2

Utsav Patel
  • 2,789
  • 1
  • 16
  • 26