0

This code is where I modified the data, wherein I update the "checked" to whether "true" or "false". and this code works because when I console.log() it it updates the state.

    setRolesData((prevState) => {
        const newState = Array.from(prevState);
        newState[targetCb]["checked"] = e.target.checked;
        return newState;
    });
    console.log(rolesData);

Image of the result: enter image description here

This code is where I loop thru the data that is updated, but the problem is it doesnt return the same data as the log data if tried for the second time.

    // get all checked roles
    const roleArr: any = [];
    rolesData.map((item, index) => {

        console.log(item.checked + " ^ " + item.name);

    });

Image of the Result: enter image description here

jmn
  • 102
  • 1
  • 8
  • Duplicate of [The useState set method is not reflecting a change immediately](https://stackoverflow.com/questions/54069253/the-usestate-set-method-is-not-reflecting-a-change-immediately). The first code snippet "works" because you modify the object that's also present in the current state. – Guy Incognito Jun 02 '23 at 06:52
  • it does not, because when i console.log() the updated state it is update. but the problem is when I loop thru the data it returns not the same. – jmn Jun 02 '23 at 06:54
  • Like I said, `newState[targetCb]["checked"] = e.target.checked` changes the object that both the new state and old state share. In the loop you add new objects. – Guy Incognito Jun 02 '23 at 06:59
  • Yes, but when I loop thru the data, why its not updated? I edited the question – jmn Jun 02 '23 at 07:04
  • Can't reproduce: https://playcode.io/1493607 Make a [mcve] – Guy Incognito Jun 02 '23 at 07:13
  • I put the loop to another method and its working now.. hehe – jmn Jun 02 '23 at 07:20

3 Answers3

0

So the problem is that the state is not updating immediately. I transferred the loop to a method wherein it handles the submission of the form.

jmn
  • 102
  • 1
  • 8
0

In React, components have a lifecycle that is based around the idea of preserving state. When you update a value in a component we effectively trigger a re-render of the component. So if you have a variable at the top of your component with a certain value and try to update this value inside a function, you'll find that this value gets reset. React is replacing the component including the JavaScript variables inside it.

In order to preserve any variables we use useState to persist the state of the component between re-renders. However, in a function, using useState does not save the value to state immediately. useState is an instruction that is sent to React that tells it that when the component re-renders, we need to save that value. If you try to access the value in state before your re-render has begun you will be using the "previous" value instead. In your case, your component will not re-render until the calling function has been completed.

So how do you listen for changes?

UseEffect is a special hook that takes an array of dependencies as "listeners". When we use useEffect and give it a value in state as a dependency, it's telling it to run the code inside the useEffect if there is a mutation to that value.

useEffect(() => {

    rolesData.map((item, index) => {
      console.log(item.checked + " ^ " + item.name);
    });

}, [rolesData]);

This code will run every time myState is changed, including on component initialisation. So we can use useEffect to process logic that requires the newly updated stateful values.

Mark Barton
  • 847
  • 6
  • 15
-2

UseState is asynchronous. So, it will not work in a loop as expected. The better approach would be to use some gloabl variable and later update your state based on it.

Musadiq Khan
  • 174
  • 7
  • useState isn't asynchronous??? It's completely synchronous. It literally causes a component to re-render, setting the new value in state happens at the very beginning of the component's lifecycle state-swap – Mark Barton Jun 02 '23 at 07:40
  • It does have an async behavior you cannot expect the update to reflect immediately as different functions are batched together as it is an expensive func. – Musadiq Khan Jun 02 '23 at 07:59
  • yes, but useState is not asynchronous. Setting the value of useState does not update it until the component re-renders. It is an asynchronous hook, but it is not asynchronous in the way that you can await it. The value change cannot happen independent of the component, it has to change when the component is re-rendered making it completely synchronous. – Mark Barton Jun 02 '23 at 08:01