132

In the past, we've been explicitly warned that calling setState({myProperty}) is asynchronous, and the value of this.state.myProperty is not valid until the callback, or until the next render() method.

With useState, how do I get the value of the state after explicitly updating it?

How does this work with hooks? As far as I can tell, the setter function of useState doesn't take a callback, e.g.

const [value, setValue] = useState(0);
setValue(42, () => console.log('hi callback');

doesn't result in the callback being run.

My other workaround in the old world is to hang an instance variable (e.g. this.otherProperty = 42) on the class, but that doesn't work here, as there is no function instance to reuse (no this in strict mode).

AnilRedshift
  • 7,937
  • 7
  • 35
  • 59
  • With hooks (`useEffect`) and the possibility to pass the current state variable around - what is your use-case for having the "tell me when you're done updating the state"? – Narigo Jan 10 '19 at 00:54
  • You could use useState with a callback function. This isn't provided by default, but this custom hook helps: https://github.com/the-road-to-learn-react/use-state-with-callback – Robin Wieruch May 31 '19 at 11:12
  • 1
    The setter function of `useState` does take a call back as explained here: https://reactjs.org/docs/hooks-reference.html#functional-updates Was this question posted before this functionality was available or something – JohnSnow Jul 21 '19 at 19:47

2 Answers2

95

You can use useEffect to access the latest state after updating it. If you have multiple state hooks and would like to track the update on only part of them, you can pass in the state in an array as the second argument of the useEffect function:

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

The above useEffect will only be called when state1 is updated and you shouldn't trust the state2 value from inside this function as it may not be the latest.

If you are curious about whether the update function created by useState is synchronous, i.e. if React batches the state update when using hooks, this answer provide some insight into it.

Claire Lin
  • 2,372
  • 8
  • 13
  • 49
    This doesn't help in my situation - state1 can be changed by multiple events, and I can't tell which event triggered the state change. Would really appreciate the old syntax `await setState(...)`. – Stanley Luo Jul 02 '19 at 00:22
  • 2
    Note that if you are using an object or array in your state you need to set that in the second array argument of `useEffect`, e.g. `useEffect(() => ..., [state.prop])` – Enijar Feb 27 '20 at 10:37
  • 1
    I need to do this inside an onPress function. However, useEffect can only be called in the body of a function component. Is there another solution? – Omar Diaa Sep 27 '20 at 09:24
  • yeah b/c this new react hooks adds more issues. react 15 was way better IMHO – jenkizenki Oct 04 '21 at 17:51
3

Well, if you refer to the relevant docs you'll find...

const [state, setState] = useState(initialState);

Returns a stateful value, and a function to update it.

During the initial render, the returned state (state) is the same as the value passed as the first argument (initialState).

The setState function is used to update the state. It accepts a new state value and enqueues a re-render of the component.

setState(newState);

During subsequent re-renders, the first value returned by useState will always be the most recent state after applying updates.

So your new state, whatever it is, is what you've just set in useState, i.e. the value of initialState. It goes directly to state, which updates reactively thereafter. Quoting further from the relevant docs:

What does calling useState do? It declares a “state variable”. Our variable is called count but we could call it anything else, like banana. This is a way to “preserve” some values between the function calls — useState is a new way to use the exact same capabilities that this.state provides in a class. Normally, variables “disappear” when the function exits but state variables are preserved by React.

If you'd like to do something whenever your state updates, then just use componentDidUpdate.(docs)

benas
  • 186
  • 5