gpt4 book ai didi

javascript - React 浅拷贝仍然触发重新渲染?

转载 作者:行者123 更新时间:2023-12-04 08:05:37 25 4
gpt4 key购买 nike

根据我对 React 的了解,您不应该改变任何对象,否则 React 不知道重新渲染,例如,当单击按钮时,以下示例不应触发 UI 中的重新渲染:

import React, { useState } from "react";
import ReactDOM from "react-dom";

function App({ input }) {
const [items, setItems] = useState(input);

return (
<div>
{items.map((item) => (
<MyItem item={item}/>
))}
<button
onClick={() => {
setItems((prevItems) => {
return prevItems.map((item) => {
if (item.id === 2) {
item.name = Math.random();
}
return item;
});
});
}}
>
Update wouldn't work due to shallow copy
</button>
</div>
);
}

function MyItem ({item}) {
const name = item.name
return <p>{name}</p>
}

ReactDOM.render(
<App
input={[
{ name: "apple", id: 1 },
{ name: "banana", id: 2 }
]}
/>,
document.getElementById("container")
);

你可以试试上面的代码 here
并且更新对象数组的正确方法应该如下所示(其他深度复制方法也可以)
 setItems((prevItems) => {
return prevItems.map((item) => {
if (item.id === 2) {
# This way we return a deepcopy of item
return {...item, name: Math.random()}
}
return item;
});
});
为什么即使我只是更新原始项目对象,第一个版本也可以正常工作并且 UI 会立即更新?

最佳答案

渲染是由于 .map创建新数组。如果您执行 prev[1].name = "x"; return prev; 之类的操作在您的钩子(Hook)中,这不会执行更新。根据 reactjs docsetState带函数参数:

If your update function returns the exact same value as the currentstate, the subsequent rerender will be skipped completely.


更新。
是的,说到亲子互动, item将是相同的(通过引用),但 child props会有所不同。你有 MyItem({ item })这个 item正在从 props 解构,比如说 MyItem(props) , 而这个 props由于父源发生更改而更改。
所以每次你 map在列表中,您明确要求父级渲染其子级,而子级的部分(或全部)参数未更改这一事实并不重要。为了证明这一点,您可以从子组件中删除任何参数:
  {items.map(() => ( <MyItem /> ))}
function MyItem () {
return <p>hello</p>
}
MyItem每次执行 items 时都会调用通过状态 Hook 更新。及其 props将始终与以前的版本不同。

关于javascript - React 浅拷贝仍然触发重新渲染?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66234458/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com