我有这段代码。
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>
);
}
如果单击“单击我”,它将增加对象的count属性。 但是由于某些原因,如果单击它,对象仍然会更新,但组件不会重新渲染。您可以使用“在日志中显示”按钮来检查对象的值。
根据reactjs.org,无论何时设置组件的状态,它都会重新呈现。但是,如果您这样写,就不会。
但是如果我将onClick函数更改为
const onClick = () => {
setObject(oldObject => {
const newObject = { ...oldObject };
newObject.count = oldObject.count + 1;
return newObject;
});
};
然后它将重新渲染组件。
任何人都可以解释造成这种奇怪行为的原因吗?
答案 0 :(得分:1)
您在第一个代码段中所做的工作更改了原始状态-在React世界中,这几乎总是不可行。通常,React通常仅在某些状态或道具已更改的情况下才转售,并且由于您对原始状态进行了突变,因此状态看起来似乎没有更改。
在第二个示例中,您将创建原始状态(const newObject = {...oldObject}
)的副本。更改副本并返回它很好-您不是在更改原始状态。
答案 1 :(得分:0)
尝试像这样设置object
:
const onClick = () => {
setObject({
count: object.count + 1
});
};
答案 2 :(得分:0)
您需要返回对象。您没有返回正确的对象。尝试这样做:
const onClick = () => {
// setObject({...object, count:object.count+1}); //another way
setObject(old => {
console.log(old)
let updatedCount = old.count + 1
return {...old,count: updatedCount};
});
};
答案 3 :(得分:0)
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 我知道这只是一个示例,但是发布此代码段很可能会使您对类型/名称情况感到困惑。
答案 4 :(得分:0)
之所以如此行事,是因为React使用Object.is comparison algorithm。
如果将状态挂钩更新为与当前状态相同的值,React将纾困,而不会渲染子代或发射效果。