0

I have a React Native app in which I am running some code that looks like the code below. Why is the following output undefined? Reading someState from useEffect is undefined even when the state is set inside the useEffect

const SomeComponent = () => {
  const [someState,setSomeState] = useState();
  
  const anFunction = () => {
    let data = 'data'
    return data
  }

  useEffect(() => {
    const theData = anFunction();
    setSomeState(theData)
    console.log(someState)
  },[])

  ...

  // later renders some component
}

I am attempting set the state and then read the state within this useEffect because I would like to implement something like:

  const doSomethingWithTheState = () => {
    //some transformation here
    setSomeState(transformedData)
  }

  useEffect(() => {
    const theData = anFunction();
    setSomeState(theData)
    
    doSomethingWithTheState()

  },[])
patataskr
  • 325
  • 5
  • 15
  • Calling `setSomeState` triggers a state update, but you don't see the updated state until the next re-render of the component. If you want some action to trigger whenever `someState` changes, you should put it in a separate `useEffect` with `someState` in the dependency array. – super May 05 '22 at 21:34
  • 2
    State updates in `useEffect` are not synchronous, and your `console.log` is referencing the current state and not the updated state. Please see this post: https://stackoverflow.com/questions/54069253/the-usestate-set-method-is-not-reflecting-a-change-immediately – gloo May 05 '22 at 21:35

4 Answers4

2

You might get something out of my answer to a similar question: React Native I can not store an array with AsyncStorage

@gloo posted a much more interesting discussion on this issue here: The useState set method is not reflecting a change immediately

Setting state is neither sync nor async. It's a quirk/feature of the React ecosystem. State is immutable in terms of a single render; therefore you'll never get the updated state until the next render.

If you need to work with the state directly after it's been changed, do it in a useEffect with the state variable in the dependency array.

Abe
  • 4,500
  • 2
  • 11
  • 25
  • between your answer and gloos answer I was able to piece together a solution to having the state available for the `useEffect` function. Kind of annoying behavior on the part of React but very interesting nonetheless. – patataskr May 06 '22 at 17:15
  • 1
    I edited @gloo's link into my answer because I feel it is a much more interesting and complete discussion of the issue. I'll be linking that from now on. Thanks! – Abe May 09 '22 at 04:41
0

It should work by adding a .then

.then(doSomethingWithTheState())
0

It is undefined because useEffect is not async. Your initial state is already undefined so you see undefined in console.log. To create async logic inside useEffect you should update like this

useEffect(() => {
    async function test(){
      //Your logic here
    } 
    test()

  },[])
Evren
  • 4,147
  • 1
  • 9
  • 16
0

Because my goal is to mutate the data within the useEffect it was better to initialize my state using the anFunction() (obviously this is still just an example). Here's what my code looks like now:

const SomeComponent = () => {
  const [someState,setSomeState] = useState(anFunction());
  
  const anFunction = () => {
    let data = 'data'
    return data
  }

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

  ...

  // later renders some component
}

I've seen of conversation about how useState is async. This is misleading. Looking at Abe's answer and his description will guide you towards resolving many weird React state-setting behaviors.

Do not try to await or async your state setting within the useEffect.

patataskr
  • 325
  • 5
  • 15