假设我有一个像这样的功能组件:
function App(){
const [obj, setObj] = useState({arr:[1,2,3,4,5]})
const swap = (a,b)=>{
const updatedArr = Object.assign(
obj.arr,
{
[a.toString()]:obj.arr[b],
[b.toString()]:obj.arr[a]
}
)
setObj(
Object.assign(
obj,
{arr:updatedArr}
)
)
};
const buttonAction = (e) => {
e.preventDefault();
swap(0,4)
}
return <div>
<button onClick = {buttonAction}>swap</button>
<ul>
{
obj.arr.map(
item=>{return <li key={item.toString()}>{item}</li>}
)
}
</ul>
</div>
}
“交换”按钮使 swap
函数交换数组的第一个和最后一个元素。当我在开发人员工具中检查这一点时,实际上发生的情况是:
但是,它不会导致重新渲染,因此列表在 View 中保持不变。
我可以通过更改交换函数以包含以下内容来强制重新渲染:
const newObj = Object.assign(
obj,
{arr:updatedArr}
)
setObj(
Object.assign(
{},
newObj
)
)
因此,通过将更新后的对象分配给新对象,我可以强制重新渲染。这是最好的方法吗?或者是否有更好的方法让组件在钩子(Hook)中的对象发生变化时重新渲染?
更新:在有人问我“更好”是什么意思之前,我的意思是更“React-y”的东西,这符合设计框架的人的意图,他们肯定已经预料到了一种情况像这样。
最佳答案
看起来您正在直接修改状态,这导致更新无法触发渲染。
setObj(
Object.assign(
obj,
{arr:updatedArr}
)
)
Object.assign
正在使用新的有序 arr 直接更改 obj 变量(您的状态)。然后 setObj 获取这个 obj 并将其分配给自己 - 此时,react 正在比较对象(与 Object.is)来决定是否需要渲染。由于它是完全相同的对象,因此不会重新渲染。
在您的工作更新中,您将分配给一个新对象,因此 react 将呈现。
也就是说,react-y 的方法是不直接修改状态(本质上是你正在做的稍微修改的事情)
const swap = (a,b)=>{
const updatedArr = Object.assign(
[...obj.arr],
{
[a.toString()]:obj.arr[b],
[b.toString()]:obj.arr[a]
}
)
setObj(
Object.assign(
{},
obj,
{arr:updatedArr}
)
)
};
关于javascript - 导致钩子(Hook)对象更新重新渲染的最佳方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57297882/