gpt4 book ai didi

Problem with updating object as a state, each update stores diff from init version of object(将对象更新为状态的问题,每次更新存储的对象与初始版本的对象不同)

转载 作者:bug小助手 更新时间:2023-10-25 19:46:56 32 4
gpt4 key购买 nike



I have object with 2 props, each of it is an object with "value" prop and another prop which is callback to function for update the "value" prop.

我有2个道具的对象,每个道具都是一个带有“Value”道具的对象,另一个道具是用于更新“Value”道具的回调函数。


Here is the full code:

以下是完整的代码:


export default function App() {

const initObj = {
name1: {
value: "",
callback: func1
},
name2: {
value: "",
callback: func2
}
}

const [obj, setObj] = useState(initObj);

function func1(val) {
const newName1 = {...obj.name1, value: val};
setObj({...obj, name1: newName1});
}

function func2(val) {
const newName2 = {...obj.name2, value: val};
setObj({...obj, name2: newName2});
}

return (
<>
<button onClick={() => obj.name1.callback("value1")}>setValue1</button>
<button onClick={() => obj.name2.callback("value2")}>setValue2</button>
<br/>
{JSON.stringify(obj)}
</>
);
}

The result is as following.

其结果如下。


First load:
{"name1":{"value":""},"name2":{"value":""}}

Click on button [setValue1]:
{"name1":{"value":"value1"},"name2":{"value":""}}

Click on button [setValue2]:
{"name1":{"value":""},"name2":{"value":"value2"}}

And so on. The Obj will never have name1.value and name2.value filled together.

诸若此类。Obj永远不会将name1.value和name2.value填充在一起。


Howewer, if I change code to this:

但是,如果我将代码更改为以下代码:


<button onClick={() => func1("value1")}>setValue1</button>
<button onClick={() => func2("value2")}>setValue2</button>

It will work. But this is not what I need. Later I want to send all props to components:

看起来不错。但这不是我需要的。稍后,我想将所有道具发送到组件:


<Button {...Obj.name1} /> <Button {...Obj.name2} />

and this also won't work.

这个也不行


更多回答
优秀答案推荐

You can change the functions like below and try

您可以像下面这样更改函数并尝试


  function func1(val) {
const newObj = { ...obj };
newObj.name1.value = val;
setObj(newObj);
}

function func2(val) {
const newObj = { ...obj };
newObj.name2.value = val;
setObj(newObj);
}

Issue: Handling of closures and state updates in functional components in JS like here, when you define func1 and func2, they capture the obj value from the initial render. So, when you call func1 or func2, they use the obj value that was present at the time of their creation that is initObj, not the updated obj value.

问题:在JS中处理函数组件中的闭包和状态更新就像这里,当您定义函数1和函数2时,它们从初始呈现捕获obj值。因此,当调用函数1或函数2时,它们使用创建时存在的obj值,即initObj,而不是更新后的obj值。


Solution: Create a copy of obj as newObj, and then directly modify the value property of newObj. This approach works as expected because it doesn't rely on closures to capture the obj value, and it directly updates the properties.

解决方案:创建obj的副本作为newObj,然后直接修改newObj的Value属性。这种方法的工作方式与预期不谋而合,因为它不依赖闭包来捕获obj值,并且直接更新属性。


更多回答

It works, but doesn't it violates React principle not to mutate object in th state? newObj is not a full copy of obj. name1 and name2 still point to the same nested objects, so you directly modify it by newObj.name1.value = val

它是有效的,但是在这个状态下不改变物体不违反反应原则吗?NewObj不是obj的完整副本。Name1和name2仍然指向相同的嵌套对象,因此您可以通过newObj.name1.value=val直接修改它

Here we're not directly mutating the state obj. Instead, we're creating a shallow copy of obj using the spread operator { ...obj } and then modifying the value property of newObj then updating the state. So, in our code, modifying newObj.name1.value or newObj.name2.value does not violate React principles

在这里,我们并不是在直接改变州对象。相反,我们使用扩散操作符{...obj}创建obj的浅表副本,然后修改newObj的Value属性,然后更新状态。因此,在我们的代码中,修改newObj.name1.value或newObj.name2.value并不违反反应原则

I have made changes in my project. Seems to work anyway. Thank you! )

我已经对我的项目进行了更改。不管怎么说,看起来挺管用的。谢谢!)

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com