说我有一个像这样的功能组件:
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
函数交换数组的第一个和最后一个元素。当我在开发人员工具中检查此情况时,实际上就是这样:
但是,它不会导致重新呈现,因此列表在视图中保持不变。
我可以通过更改交换功能以包含以下内容来强制重新渲染:
const newObj = Object.assign(
obj,
{arr:updatedArr}
)
setObj(
Object.assign(
{},
newObj
)
)
因此,通过将更新的对象分配给新对象,我可以强制重新渲染。这是最好的方法吗?还是有更好的方法让挂钩中的对象发生更改时重新渲染组件?
更新:在有人问我“更好”是什么意思之前,我的意思是更“反应准确”,这与设计框架的人员的意图一致,他们肯定已经预见到了情况像这样。
答案 0 :(得分:2)
您似乎正在直接修改状态,这导致更新不会触发渲染。
setObj(
Object.assign(
obj,
{arr:updatedArr}
)
)
Object.assign
使用新的有序arr直接更改obj变量(您的状态)。然后setObj
正在获取此obj并将其分配给自身-此时,react正在比较对象(与Object.is
)以确定是否需要渲染。由于它是完全相同的对象,因此不会重新渲染。
在您的工作更新中,您正在分配一个新对象,因此react将呈现。
也就是说,反应的方法是不直接修改状态(本质上就是稍加修改即可完成的操作)
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}
)
)
};