简体   繁体   中英

How to set a state in a forEach loop using useState hook

I want to transfer data in an array A into a object B, so i doing something like [array].forEach(e => setB({...B, e})), but it seems like when traversing on later elements, former actions have been "forgotten", how should i achieve my goal?
Prototype should looks like this:

import React from "react"
import {Map} from "immutable"

export default function App() {
    const [arrayA, setA] = React.useState([1, 2]);
    const [objB, setB] = React.useState(Map({}));
    React.useEffect(() => {
        arrayA.forEach(num => {
            setB(objB.set(num, num*num));
        })
    }, [])

    return (<div>null</div>)
}

Thanks in advance!

You are correct. With a regular value state update in a loop each subsequent enqueued update overwrites the previous update, so the last update is the one used for the next render cycle.

Solution

Normally you would use a functional state update to update from the previous state, not the state from the previous render cycle. In this case it makes more sense to map the arrayA state to an array of key-value pairs and do a single update for the objB state.

React.useEffect(() => {
  setB(Map(arrayA.map(num => [num, num * num]));
}, []);

You're getting stale data and you should use setState callback like this:

export default function App() {
  const [arrayA, setA] = React.useState([1, 2]);
  const [objB, setB] = React.useState(Map({}));
  React.useEffect(() => {
    arrayA.forEach((num) => {
      setB(oldValue => oldValue.set(num, num * num));
    });
  }, []);

  return <div>null</div>;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM