0

Throughout my application I am modifying state through useState(), for example:

const [question, setQuestion] = useState('')

const updateQuestionHandler = () => {
  let honestQuestion = 'is this a race condition?'
  setQuestion(honestQuestion)
  console.log(question)  // Returns => '' or the previous state, why isn't the updated state returned instead?
}

return (
  <div> 
    <p> { question } </p> // This is generally updated correctly, after the button click below
    <button onClick={() => updateQuestionHandler()}> Click to update question </button>
  </div> 
)

What is happening above is, once I update state with setQuestion(variable), the state gets updated (eventually). How can I ensure that the state has been updated and is safe for reference after setting it?

You can see where I try to console.log() the updated state, right after setting it, the previous or old state gets returned. I could instead console.log(honestQuestion) , is that the correct thing to do? I feel like I should be using state as the single source of truth.

bruh
  • 2,205
  • 7
  • 30
  • 42
  • `setState` is asynchronous. See the posted answer. – Adam Azad Dec 01 '20 at 15:43
  • Simply put, updating state is asynchronous. The linked duplicate goes into more detail as to why. But to answer the question, where you are currently using `console.log` you would indeed log `honestQuestion` if that's the information you want to see on the console and that's the time at which you want to see it. – David Dec 01 '20 at 15:43
  • The attached "duplicate" uses the class based `this.setState({})` which allows callbacks, which would allow me to accomplish what I was trying to do in the original question. Callbacks are not supported in `useState()` hooks. Its valuable that you mentioned updating state is asynchronous, I appreciate that - but the linked post doesn't answer the question of "how" I safely use the updated state after a change with hooks – bruh Dec 01 '20 at 16:08

1 Answers1

2

To do something after a hook state was updated you need to use a useEffect and pass the state to the dependencies array

useEffect(() => {
    console.log(question)
},[question]) 

This will only run after every time the question state is updated.

Shmili Breuer
  • 3,927
  • 2
  • 17
  • 26
  • 1
    This is valuable thanks. I looks like I need to alter the way I'm referencing state after a change. Meaning, instead of directly calling `console.log(updatedState)` inside the function that is updating it, create a separate function instead, that only gets run by `useEffect()` after a state change. From there, I can "safely" rely on `question` or whatever `updatedState` to have been updated – bruh Dec 01 '20 at 16:13
  • 1
    @bruh you are correct. – Shmili Breuer Dec 01 '20 at 16:15