Home > Net >  Value isn't be updated async in React useState (React)
Value isn't be updated async in React useState (React)

Time:11-10

I want to change State with child elements in React. However, when I click once, it is not immediately updated. Click twice, it shows the correct answer.

How to update async?

export default function Example() {
  const onClick = async () => {
   console.log('a', test)
   // should be 'b', but console log 'a'
  }

  const [test, setTest] = useState('a')
  
  return (
    <ClickExample setTest={setTest} onClick={onClick} />
  )
}
export default function ClickExample() {
  const next = useCallback(
    (alphabet: string) => {
      setTest(alphabet)
      onClick()
    },
    [onClick, setTest],
  )

  return <SelectButton onClick={() => next('b')} />
}

CodePudding user response:

You can receive the value to be updated as an argument from the onClick callback. It'll be something like this:

export default function Example() {
  const [test, setTest] = useState('a')

  const handleClick = (newValue) => {
    setTest(newValue);
  }
  
  return (
    <ClickExample onClick={handleClick} />
  )
}

export default function ClickExample({ onClick }) {
  return <SelectButton onClick={() => onClick('b')} />
}

NOTE: You should avoid using useCallback() when it is not necessary. Read more over the web but this article from Kent C. Dodds is a good start. As a rule of thumb: Never use useCallback()/useMemo() unless you REALLY want to improve performance after needing that improvement.

CodePudding user response:

In the first render, the value of test is equal to'a'. So when the console.log is executed, it has already captured 'a' as the value of test state. (See closures and stale closures).

One way to fix this would be to create a handleClick function in the parent component which receives the new value of test as its input and set the state and log the new value(which will be updated in the next render) using its argument.

  // ClickExample
  const handleClick = (alphabet) => {
    setTest(alphabet);
    console.log('a', alphabet);
  };

codesandbox

  • Related