简体   繁体   中英

Update Array State on React using Hooks replaces instead of concat

I have this hook:

const [pastChat, setPastChat] = useState([]);

I'm updating it with a function that it's called when the user presses a button:

const nextAction = (step) => {
    //...do a bunch of things...
    let nextInLine = [array with an object];
    setPastChat(pastChat.concat(nextInLine));
}

This code works just fine, but when I try to run this setPastChat() in a loop (while or for loop) it just replaces the last item instead of concat() it. I'm using concat because push() does not work as well. So I have something like this:

const nextActionLoop = (step) => {
    //...do a bunch of things...
    let nextInLine = [array with an object];
    let index = 0;
    while(index < 5) {
        //...change nextInLine's object;
        setPastChat(pastChat.concat(nextInLine));
        index = index + 1;
    }
}

I'm not sure why this is happening, but I tried to log pastState and even in the function that works the state appears not the be updated after setPastChat(pastChat.concat(nextInLine)); . It does update my view correctly, but it might do this a while after. I have no idea and I'd like to know how can I just concat new items in the while loop, please.

I thank you in advance!

Use a functional state update to correctly enqueue multiple state updates. The issue is that all the queued updates use the same pastChat state value from the current render cycle, so each update overwrites the previous one and the last update is the one you see.

const nextActionLoop = (step) => {
    //...do a bunch of things...
    let nextInLine = [array with an object];
    let index = 0;
    while(index < 5) {
        //...change nextInLine's object;
        setPastChat(pastChat => pastChat.concat(nextInLine));
        index = index + 1;
    }
}

This will use the previous state and compute the next state value.

Here's a demo of mine that demonstrates the difference between a regular update and a functional update, and why the functional update works for multiple enqueued updates.

编辑反应 - 定期和功能状态更新

I don't know the process time in your loop, but if it's not slow and sync, you should first concat all your pastChat and then update the state:

const nextActionLoop = (step) => {
    //...do a bunch of things...
    const iterations = 5;
    const newPastChat = Array(iterations).fill().map((_, i) => {
      const nextInLine = {...};

      return nextInLine;
    });

    setPastChat(newPastChat);
}

btw you're free of mutations, only functional code;)

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