即使道具没有改变,为啥还要对重新渲染组件做出反应?

Posted

技术标签:

【中文标题】即使道具没有改变,为啥还要对重新渲染组件做出反应?【英文标题】:Why react rerendres components even if props didn't changed?即使道具没有改变,为什么还要对重新渲染组件做出反应? 【发布时间】:2021-07-16 17:59:18 【问题描述】:

我玩了一段时间的 react 并阅读了文档,我发现一些对我来说似乎很奇怪的东西,为什么即使子 props 相同,为什么在父级的每次状态更改时都会对组件的子元素进行重新渲染? ? 为什么我应该将我的组件包装在 Memo() 中以防止这种重新渲染? 让 Memo 成为每个 React 组件的默认值不是更好,还是应该将它用于我的所有组件。

【问题讨论】:

这就是 react 的工作原理。即使正在更新的状态没有传递给孩子,它也会重新呈现。如果您不想让孩子重新渲染,则需要使用备忘录。 相关:***.com/questions/61301937/… 【参考方案1】:

在每次状态变化时,react 都会触发一个 render 函数,该函数会调用其子组件来 rerender,请找到以下示例来解决您的问题,或访问 @987654321 @

function Parent() 
const [item, setItem] = useState( name: "item", value: 0 );

const handleChangeItem = useCallback(() => 
  setItem(prevItem => ( ...prevItem, value: prevItem.value + 1 ));
, []);

return (
 <>
   Name: item.name Value: item.value
   <Child changeItem=handleChangeItem />
 </>
 );


const Child = React.memo(function Child( item, changeItem ) 
 function handleClick() 
   changeItem();
 
console.log("child render");
return (
   <div>
    <button onClick=handleClick>change state in parent</button>
   </div>
 );
);

【讨论】:

【参考方案2】:

memo 是 PureComponent 的实现,但用于功能组件。 PureComponent 会对类组件中的 props 进行浅层比较,而对于功能组件,您使用 memouseMemo(用于记忆值)和 useCallback(用于记忆函数)。

【讨论】:

将组件包装在备忘录函数中总是好的吗?如果不是什么时候使用它? 当我将回调作为道具传递时,我会将我的组件包装在 memo 中(然后回调必须包装在 useCallback 中)。每次父组件重新渲染时,它都会创建一个新的回调函数并将其发送给它的子组件。孩子“看到”了一个新功能(因为它是一个不同的对象)并重新渲染,因为一个新的道具来了。 useCallback 记忆回调函数,memo 将你的组件变成一个纯 FC,它将执行 props 的浅层比较。这是一个很好的resource【参考方案3】:

尝试在每次状态更改时使用 PureComponents 作为反应重新渲染,如果您的父组件重新渲染,那么您的所有子组件也将以相同的顺序重新渲染。为避免重新渲染子组件,您可以使用 React.Memo、useMemo 或 useCallback。虽然不是每次都记住组件。

【讨论】:

以上是关于即使道具没有改变,为啥还要对重新渲染组件做出反应?的主要内容,如果未能解决你的问题,请参考以下文章

当状态改变时,对文本字段做出反应 onChange 更新整个组件

反应父母对孩子道具传递而不重新渲染

即使状态没有改变,为啥 setState 会导致太多的重新渲染错误

Vue 没有对计算的 props 更改做出反应

在不改变状态、道具或父级的情况下反应子级渲染

反应:孩子点击改变父母的状态以重新渲染