【问题标题】:React state is not being updated using useState()没有使用 useState() 更新反应状态
【发布时间】:2020-11-19 05:30:56
【问题描述】:

我想更新一个多维数组。
我有这个状态变量。

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

一个实体数据集的结构是最初的。

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

一旦触发更新功能,我必须定期更新此数据。

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)
    }

虽然状态更新,但travelledDataSet[0] 的大小仍然为 2。而且,travelledDataSet[0][1] 只是在更新。
例如

// 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. 

为了检查为什么这不起作用,我在更新函数之外创建了另一个变量(不是反应状态)。

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)
    }

函数完成后,将打印此代码console.log("AR: ",ar[0],"Data:",travelledDataSet[0])

您可以在下图中看到,ar[0] 的长度为 58,而 travelledDataSet[0] 的长度仅为 1。

即使这样也不起作用setTravelledDataSet(JSON.parse(JSON.stringify(tempData)));

可重现的代码:

// 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])

每当display 发生变化时,我必须从一开始就做同样的事情。该组件大约有数千行代码。我在这里添加代码,可以简要说明问题。

【问题讨论】:

  • 您似乎可能在一个循环中将多个更新排入队列,但是使用如此最少的代码 sn-p 很难理解您要做什么。您可以更新以包含Minimal, Complete, and Reproducible 组件代码示例吗?使用JSON.parse(JSON.stringify(...)) 是克隆对象的糟糕方式,不推荐使用。看起来你的更新函数总是用tempData[0].push 更新第一个嵌套数组。为什么外部数组的每个元素都只是一个双嵌套数组?
  • @DrewReese Can you update to include a Minimal, Complete, and Reproducible component code example?我添加了代码sn-p。
  • @DrewReese JSON.parse(JSON.stringify(...)) 我正在寻找解决方案,所以我只是使用JSON.parse(JSON.stringify(...)) 进行了测试。

标签: javascript reactjs use-state


【解决方案1】:

为什么要递归定时调用更新;在update() 内调用setTimeout(update, 10)?这个成语我以前没见过,看起来很腥。或许看看setInterval

还可以考虑使用useEffect 挂钩来处理数据更改时的副作用,而不是箭头函数。

我认为你应该重构这段代码。很难读。

【讨论】:

  • I have not seen this idiom before 是的,这不是一个好习惯。我用它来测试这个解决方案是否对我有用。我正在与mapbox-gl-js 合作,我遇到了问题。
  • 所以,主要问题是为什么状态没有被更新,而如果我热衷于另一个数组(不是反应状态)那么它工作正常。
【解决方案2】:

您的“循环计数器”i 在每个渲染周期重新声明,即每次组件渲染 i 等于 1。

由于我仍然不清楚为什么状态如此复杂以及您的状态更新在这里试图完成的事情,我认为这可能是一个简单的“修复”。使用 i 循环计数作为传递的参数,并在启动递归时最初传递 1。您还应该将 update 函数声明移动到 useEffect 挂钩中,以将其作为依赖项删除。

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])

【讨论】:

  • each time the component renders i equals 1. 我希望每次组件呈现时它都是一个。但是,我不希望这是一个,每次组件更新时。它工作正常。
  • let ar=JSON.parse(JSON.stringify(travelledDataSet)) 这个解决方案暂时对我有用。 // 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. 你可以在这里看到状态更新,但不是我希望的那样。
  • let ar=JSON.parse 这个数组也有相同的结构,在这里它工作得很好。但是,travelledDataSet 也共享相同的结构,但在这里它不起作用。
  • You should also move the update function declaration into the useEffect hook to remove it as a dependency.你能详细说明一下吗?
  • @rahulkumar 我不确定我是否遵循期望组件在更新时不会重新呈现的逻辑。如果您更新状态,组件 重新呈现。您能否尝试创建一个 running 代码框示例来重现该问题以供我们调试?
猜你喜欢
  • 2023-04-02
  • 2021-01-14
  • 2021-04-17
  • 1970-01-01
  • 2020-07-22
  • 2020-04-19
  • 2020-12-01
  • 1970-01-01
相关资源
最近更新 更多