Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How can I update State properly in switch case in a loop

I want to update state like [1, 2, 3] but what I’m wrong here and how to fix it.

codesanbox: https://codesandbox.io/s/infallible-mendeleev-6641iw?file=/src/App.js:0-642

import "./styles.css";
import { useEffect, useState } from "react";

export default function App() {
  const [value, setValue] = useState([]);

  useEffect(() => {
    run();
  }, []);

  const run = () => {
    for (let i = 0; i < 10; i++) {
      let copy = i;
      switch (copy) {
        case 1:
          setValue([...value, copy]);
          break;
        case 2:
          setValue([...value, copy]);
          break;
        case 3:
          setValue([...value, copy]);
      }
    }
  };

  return (
    <div className="App">
      {value.map((item, index) => {
        return <h2>{value[index]}</h2>;
      })}
    </div>
  );
}

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

The problem is that every time you do setValue([...value, copy]), you’re overwriting the previous time you did it. value is unchanging in that loop.

Instead, build the new array and then set it in state. And any time you’re building new state based on existing state, it’s generally best to use the callback form of the state setter (to ensure that you’re not starting with a stale version of value).

Example:

const run = () => {
    setValue((oldValue) => {
        const newValue = [...oldValue];
        for (let i = 0; i < 10; i++) {
            let copy = i; // ** There's no need for this, just use `i`
            switch (copy) {
                case 1:
                    newValue.push(copy); // It's not clear to me why...
                    break;
                case 2:
                    newValue.push(copy); // ...every case does the same..
                    break;
                case 3:
                    newValue.push(copy); // ...thing, but I replicated it
                    break;
            }
        }
        return newValue;
    });
};

Old version showing the problem:

const { useEffect, useState } = React;

/*export default*/ function App() {
    const [value, setValue] = useState([]);

    useEffect(() => {
        run();
    }, []);

    const run = () => {
        for (let i = 0; i < 10; i++) {
            let copy = i;
            switch (copy) {
                case 1:
                    setValue([...value, copy]);
                    break;
                case 2:
                    setValue([...value, copy]);
                    break;
                case 3:
                    setValue([...value, copy]);
            }
        }
    };

    return (
        <div className="App">
            {value.map((item, index) => {
                return <h2>{value[index]}</h2>;
            })}
        </div>
    );
}
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<App />);
<div id="root"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>

New version showing the solution:

const { useEffect, useState } = React;

/*export default*/ function App() {
    const [value, setValue] = useState([]);

    useEffect(() => {
        run();
    }, []);

    const run = () => {
        setValue((oldValue) => {
            const newValue = [...oldValue];
            for (let i = 0; i < 10; i++) {
                let copy = i; // ** There's no need for this, just use `i`
                switch (copy) {
                    case 1:
                        newValue.push(copy); // It's not clear to me why...
                        break;
                    case 2:
                        newValue.push(copy); // ...every case does the same..
                        break;
                    case 3:
                        newValue.push(copy); // ...thing, but I replicated it
                        break;
                }
            }
            return newValue;
        });
    };

    return (
        <div className="App">
            {value.map((item, index) => {
                return <h2>{value[index]}</h2>;
            })}
        </div>
    );
}
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<App />);
<div id="root"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>

Side note: You need key props on those h2 elements in the map callback.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading