Home > Net >  Why does view update but not the state variable?
Why does view update but not the state variable?

Time:07-29

I'm creating an app with React and I'm struggeling with state variables. An example:

import { useEffect, useState } from "react";

export default function App() {
  const [a, setA] = useState(["inital"]);

useEffect(() => {
    setTimeout(() => {
      setA(["hello"]);
    }, 1000);
  
    setTimeout(() => {
      setA([...a, " world"]);
    }, 2000);
}, []);

return (
    <div>{a}</div>
  );
}

Mutating State Functional Component Forked

The result in the view is:

0 sec: initial

1 sec: hello

2 sec: initial world

What I expected:

0 sec: initial

1 sec: hello

2 sec: hello world

It's confusing because the state hello was definitely set like you can see in the view. Why does a has the value initial in the second timeout?

CodePudding user response:

setA([...a, " world"]); is taking the value at the time when you create your function (before the wait, so before the first setTimeout callback is called). At this time the value is "initial"

If you want it to update properly you could use

setA(prev => [...prev, " world"]);

This will get the value of the state when the setA function is actually called and give you the correct result.

CodePudding user response:

This is related to closure - At the time of creation, the line setA([...a, " world"]) still refers to the initial a. You can solve this by a second useEffect which will have a as a dependency, but then you'll probably run into an infinite loop, so you might have to include a condition.

useEffect(() => {
    setTimeout(() => {
      setA(["hello"]);
    }, 1000);
}, []);

useEffect(() => {
    if (a.length === 1) {
        setTimeout(() => {
          setA([...a, " world"]);
        }, 2000);
    }
}, [a]);

    
}, []);
  • Related