javascript - 在保持引用相等的同时在 react 中传播 props
问题描述
想象一下,我有一个动态生成组件的一些道具的函数,我想一次将它们全部传递出去,而不需要明确说明该函数可以生成的每个道具。通常您可以使用扩展运算符来执行此操作,但扩展运算符的问题是它每次都创建一个新对象。这意味着(如果我理解正确的话)在React Reconciliation期间,组件每次都会有新的道具并且每次都会重新渲染,即使函数生成的道具是相同的。
这是一个具体的例子:
const generateProps = () => ({foo: 'bar'});
const ParentComponent = () => ({
const someProps = generateProps();
return (
<SomeComponent><ChildComponent {...someProps} otherProp='hello world'/></SomeComponent>
)
})
这里 ChildComponent 每次ParentComponent
都会渲染(对吗?)。我知道您可以做的一件事是ChildComponent
用 a包装React.memo
并对道具进行更深入的比较(将自定义比较函数传递给它),但是如果您无法控制ChildComponent
呢?你是不是被逼得直言不讳?或者我不正确并且ChildComponent
不会在这个例子中重新渲染(假设ChildComponent
只是消耗道具并且不使用任何上下文或任何东西)。
谢谢!
解决方案
你错了。和解不看道具。它主要看组件类型,例如
如果在一个渲染中渲染
<Comp1/>
并在下一次渲染时,在组件树的同一位置渲染:
<Comp2/>
它将卸载Comp1
和安装Comp2
,因为组件的类型不同。如果组件类型相同,它将更新现有的。还有一些详细信息,但您可以自己检查。
此外,如果您使用 ,默认情况下也会以浅层方式比较道具React.memo
,因此如果在一个渲染中您通过
let y = {a:1,b:2};
....
<Comp1 {...y}/>
在下一次渲染中你通过
let x = {a:1,b:2};
...
<Comp1 {...x}/>
默认比较React.memo
会假设 props 没有改变,因为a
和b
具有相同的值。您可以在此处验证,单击div
不会重新渲染Test
组件:
let Test = React.memo(props => {
console.log(props);
return <div>{props.a}</div>;
});
function App() {
let [state, setState] = React.useState({ a: 123 });
return (
<div
onClick={() => {
setState({ a: 123 });
}}
>
<h1>Hello StackBlitz!</h1>
<Test {...state} />
<p>Start editing to see some magic happen :)</p>
</div>
);
}
ReactDOM.render(
<App />,
document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="react"></div>
推荐阅读
- c - 在 C 中格式化 printf() 字符串时,最小字段宽度有什么意义?
- javascript - 当您按下“确定”(Javascript)时,如何制作一个下载图像的确认框
- java - Java:Do-while 循环,偶数然后再试一次
- google-apps-script - 谷歌应用脚本触发单元格值更改
- svg - 如何修复在 Safari 中不起作用的 SVG 动画
- python - 在 Scrapy 中抓取目标价格
- linux - Powershell中输入行上的ANSI转义码
- php - 如何从 JSON 中获取密钥
- firebase - Firebase 分析 (6.3.0) 注意:使用或覆盖已弃用的 API
- c++ - LNK1104 仅在调试模式下发生