React Hooks useState 与 Object 不一致
React Hooks useState is not consistent with Object
我有这段代码。
import React, { useState, useEffect } from 'react';
export default function Example() {
const [object, setObject] = useState({
count: 0
});
const onClick = () => {
setObject(old => {
old.count = old.count + 1;
return old;
});
};
return (
<div>
<p>You clicked {object.count} times</p>
<button onClick={e => console.log(object.count)}>Show in log</button>
<button onClick={onClick}>Click me</button>
</div>
);
}
如果单击 "Click me",将增加对象的计数 属性。
但是由于某些原因,如果您单击它,对象仍然会更新,但组件不会重新渲染。您可以使用 "Show in log" 按钮检查对象的值。
根据reactjs.org,每当您设置组件的状态时,它都会重新渲染。但是这样写就不行了
但是如果我将 onClick 函数更改为
const onClick = () => {
setObject(oldObject => {
const newObject = { ...oldObject };
newObject.count = oldObject.count + 1;
return newObject;
});
};
然后它将重新渲染组件。
任何人都可以解释导致这种奇怪行为的原因吗?
您在第一个代码片段中所做的事情 改变了 原始状态——这在 React 中几乎总是 大忌世界。 React 通常仅在某些状态或道具发生变化时才重新渲染,并且由于您改变了原始状态,因此看起来状态并没有发生变化。
在您的第二个示例中,您创建了原始状态的副本 (const newObject = {...oldObject}
)。改变副本并返回它很好——你没有改变原始状态。
尝试像这样设置 object
:
const onClick = () => {
setObject({
count: object.count + 1
});
};
您需要return反对。你不是 returning 正确的对象。尝试这样做:
const onClick = () => {
// setObject({...object, count:object.count+1}); //another way
setObject(old => {
console.log(old)
let updatedCount = old.count + 1
return {...old,count: updatedCount};
});
};
setObject 是一个调度函数。 React 设计它的方式,你唯一需要提供的是一个新值,这个值被认为是一个改变的状态。
你所做的是,你向调度函数提供一个函数类型,然后改变作为函数参数给你的对象。
你做什么
const onClick = () => {
setObject(old => { // <-- a function is provided here
old.count = old.count + 1;
return old;
});
};
你需要做什么
const onClick = () => {
setObject({...object, count: object.count + 1});
// this way no mutation of the original state value is happening,
//and you are guaranteed to have a re-render.
};
并且请停止调用变量 object 和 setObject 我知道这只是一个例子,但是发布这个代码片段很可能会得到你对 type/name 情况感到困惑。
之所以会这样是因为 React 使用 Object.is comparison algorithm.
如果您将 State Hook 更新为与当前状态相同的值,React 将在不渲染子项或触发效果的情况下退出。
我有这段代码。
import React, { useState, useEffect } from 'react';
export default function Example() {
const [object, setObject] = useState({
count: 0
});
const onClick = () => {
setObject(old => {
old.count = old.count + 1;
return old;
});
};
return (
<div>
<p>You clicked {object.count} times</p>
<button onClick={e => console.log(object.count)}>Show in log</button>
<button onClick={onClick}>Click me</button>
</div>
);
}
如果单击 "Click me",将增加对象的计数 属性。 但是由于某些原因,如果您单击它,对象仍然会更新,但组件不会重新渲染。您可以使用 "Show in log" 按钮检查对象的值。
根据reactjs.org,每当您设置组件的状态时,它都会重新渲染。但是这样写就不行了
但是如果我将 onClick 函数更改为
const onClick = () => {
setObject(oldObject => {
const newObject = { ...oldObject };
newObject.count = oldObject.count + 1;
return newObject;
});
};
然后它将重新渲染组件。
任何人都可以解释导致这种奇怪行为的原因吗?
您在第一个代码片段中所做的事情 改变了 原始状态——这在 React 中几乎总是 大忌世界。 React 通常仅在某些状态或道具发生变化时才重新渲染,并且由于您改变了原始状态,因此看起来状态并没有发生变化。
在您的第二个示例中,您创建了原始状态的副本 (const newObject = {...oldObject}
)。改变副本并返回它很好——你没有改变原始状态。
尝试像这样设置 object
:
const onClick = () => {
setObject({
count: object.count + 1
});
};
您需要return反对。你不是 returning 正确的对象。尝试这样做:
const onClick = () => {
// setObject({...object, count:object.count+1}); //another way
setObject(old => {
console.log(old)
let updatedCount = old.count + 1
return {...old,count: updatedCount};
});
};
setObject 是一个调度函数。 React 设计它的方式,你唯一需要提供的是一个新值,这个值被认为是一个改变的状态。
你所做的是,你向调度函数提供一个函数类型,然后改变作为函数参数给你的对象。
你做什么
const onClick = () => {
setObject(old => { // <-- a function is provided here
old.count = old.count + 1;
return old;
});
};
你需要做什么
const onClick = () => {
setObject({...object, count: object.count + 1});
// this way no mutation of the original state value is happening,
//and you are guaranteed to have a re-render.
};
并且请停止调用变量 object 和 setObject 我知道这只是一个例子,但是发布这个代码片段很可能会得到你对 type/name 情况感到困惑。
之所以会这样是因为 React 使用 Object.is comparison algorithm.
如果您将 State Hook 更新为与当前状态相同的值,React 将在不渲染子项或触发效果的情况下退出。