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! )
我已经对我的项目进行了更改。不管怎么说,看起来挺管用的。谢谢!)
我是一名优秀的程序员,十分优秀!