防止在包装器组件中启动 useState 的兄弟组件的重新渲染
Posted
技术标签:
【中文标题】防止在包装器组件中启动 useState 的兄弟组件的重新渲染【英文标题】:Prevent rerender of sibling component which initiates a useState in wrapper component 【发布时间】:2020-07-18 23:36:09 【问题描述】:我对 React 不是很有经验,但我有一个非常简单的设置。
export default function App()
const [title, setTitle] = useState("still-empty");
const myFunction = title =>
setTitle(title);
;
return (
<div className="App">
<ComponentA myFunction=myFunction />
<br />
<br />
<ComponentB title=title />
</div>
);
const ComponentA = ( myFunction ) =>
console.log("Rendering Component A");
return (
<div onClick=() => myFunction(Math.random() * 1000)> Component A </div>
);
;
export default ComponentA;
const ComponentB = ( title ) =>
return <div> Title : title</div>;
;
export default ComponentB;
这里有一个沙盒来测试这个:https://codesandbox.io/s/musing-cookies-g7szr
请注意,如果您单击“ComponentA”,则会重新渲染确切的 ComponentA(您可以在控制台中看到它),尽管该组件上没有任何道具发生更改。这是我真实用例的简化示例。在我的真实用例中,ComponentA 是一张包含很多东西(缩放、居中)的地图 将被重置。我想防止这些重置以及重新渲染所需的 1 秒。因此,我提出这个简化的例子。
那么如何在不重新渲染 ComponentA 本身的情况下将信息从 ComponentA 传递到 ComponentB?感谢您在这里提供帮助。
【问题讨论】:
您正在更改父组件的状态,这会重新渲染父组件及其子组件,即 ComponentA 和 ComponentB。如果你经常做这样的事情并且不想要任何不必要的重新渲染,那么你可能应该看看像 Redux 这样的东西来允许子组件直接访问状态。 感谢您的回答。是的,我改变了父母的状态。但是 ComponentA 不使用这个状态变量。那么为什么会重新渲染呢?有办法解决吗? ComponentA 不使用状态变量并不重要。当您调用 setState 时,React 会将您的母公司标记为脏并触发它的重新渲染(以及它的子组件 A 和 B)。即使状态中的值没有改变(即如果你传递它已经拥有的相同值),调用 setState 仍然会触发重新渲染。 【参考方案1】:在 Parent 中使用 useCallback
这样函数就不会一次又一次地创建,而只会在初始渲染时创建。
使用React.memo
以便在没有更改任何道具时组件不会重新渲染。
应用
export default function App()
const [title, setTitle] = useState("still-empty");
const myFunction = useCallback(title =>
setTitle(title);
, []);
return (
<div className="App">
<ComponentA myFunction=myFunction />
<br />
<br />
<ComponentB title=title />
</div>
);
组件A
import React, memo from "react";
const ComponentA = ( myFunction ) =>
console.log("Rendering Component A");
return (
<div onClick=() => myFunction(Math.random() * 1000)> Component A </div>
);
;
export default memo(ComponentA);
工作演示在这里: https://codesandbox.io/s/affectionate-boyd-v7g2t?file=/src/App.js
【讨论】:
非常感谢。这也适用于我的真实示例。非常感谢。以上是关于防止在包装器组件中启动 useState 的兄弟组件的重新渲染的主要内容,如果未能解决你的问题,请参考以下文章
React 通过使用 useState 的功能变体来防止重新渲染
如何从 vue-fullpage 包装器中的子组件调用 fullpagejs 方法?