简体   繁体   中英

React state is not being updated using useState()

I want to update a multidimensional array.
I have this state variable.

const [travelledDataSet, setTravelledDataSet] = useState(JSON.parse(JSON.stringify(solidDataSet)));

The structure of a solid dataset is initially.

export const solidDataSet = [
    [
        [76.92025126928692, 31.815485031139886]
    ],
    [
        [76.92737521643127, 31.76427071949966]
    ],
    [
        [76.91587390417601, 31.75230203493911]
    ]
]

I have to update this data at a time interval once update function is triggered.

const update=()=>{
        if(i>=dataSet[0].length) return;
        let tempData = JSON.parse(JSON.stringify(travelledDataSet));
        tempData[0].push(dataSet[0][i]);
        setTravelledDataSet(tempData);
        i++; // increment to next position
        setTimeout(update,100)
    }

Although state updates, but travelledDataSet[0] remains of size 2. And, travelledDataSet[0][1] is only being update.
For example

// first__update__is
// -- travelledDataSet[0] --
[76.92025126928692, 31.815485031139886]
[77.06221522802589, 31.75536733328293]

// in__second__update
// --travelledDataSet[0]--
[76.92025126928692, 31.815485031139886]
[77.0603269528807, 31.75317784482199] -- only this is being updated each time. 

To inspect why this is not working I created another variable (not react state) outside the update function.

let ar=JSON.parse(JSON.stringify(travelledDataSet))
    const update=()=>{
        if(i>=dataSet[0].length) return;
        let tempData = JSON.parse(JSON.stringify(travelledDataSet));
        tempData[0].push(dataSet[0][i]);
        ar[0].push(dataSet[0][i]);
        console.log("AR: ",ar[0],"Data:",travelledDataSet[0]); // ---- this is updating
        setTravelledDataSet(tempData);
        i++; // increment to next position
        setTimeout(update,10)
    }

after completion of the function, this code console.log("AR: ",ar[0],"Data:",travelledDataSet[0]) prints. 在此处输入图片说明

You can see in the image below, ar[0] has a length 58 while travelledDataSet[0] length is only 1.

Even this also doesn't worked setTravelledDataSet(JSON.parse(JSON.stringify(tempData)));

reproducible code:

// it will render solid route indecating traveled route
    const [travelledDataSet, setTravelledDataSet] = useState(JSON.parse(JSON.stringify(solidDataSet)));
    // update route -- only in development for simulation purpose
    let i = 1;
    const update=()=>{
        if(i>=dataSet[0].length) return;
        let tempData = JSON.parse(JSON.stringify(travelledDataSet));
        tempData[0].push(dataSet[0][i]);
        setTravelledDataSet(JSON.parse(JSON.stringify(tempData)));
        i++; // increment to next position
        setTimeout(update,10)
    }
    useEffect(()=>{
        setTravelledDataSet(JSON.parse(JSON.stringify(solidDataSet)));
        if(display)
            update()
    },[display])

Whenever display changes, i have to do the same thing from start. The component is about thousands line of code. I add the code here which can briefly explain the question.

Why are you making a recursive timed call to update; calling setTimeout(update, 10) within update() ? I have not seen this idiom before, and it looks fishy. Perhaps look at setInterval ?

Also consider useEffect hook to handle side effects when the data changes, instead of an arrow function.

I think you should restructure this code. It is hard to read.

Your "loop counter" i is redeclared each render cycle, ie each time the component renders i equals 1.

Since it still isn't clear to me why the state is so convoluted and what your state update is trying to accomplish here is what I think may be a simple "fix". Consume the i loop count as a passed parameter and initially pass 1 when initiating the recursion. You should also move the update function declaration into the useEffect hook to remove it as a dependency.

useEffect(() => {
  const update = (i) => { // <-- consume i loop counter
    if(i >= dataSet[0].length) return;

    const tempData = JSON.parse(JSON.stringify(travelledDataSet));
    tempData[0].push(dataSet[0][i]);
    setTravelledDataSet(JSON.parse(JSON.stringify(tempData)));
    
    setTimeout(() => update(1 + 1), 10); // <-- increment i
  }

  setTravelledDataSet(JSON.parse(JSON.stringify(solidDataSet)));

  if (display) {
    update(1); // <-- initial seed 1
  }
}, [display])

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