想象一下,我有一个动态生成组件的一些 Prop 的函数,我想一次传递所有这些 Prop ,而不是明确说明该函数可以生成的每个 Prop 。通常您可以使用展开运算符来执行此操作,但展开运算符的问题是它每次都创建一个新对象。这意味着(如果我理解正确的话)在 React Reconciliation 期间,组件每次都会有新的 props,并且每次都会重新渲染,即使函数生成的 props 是相同的。
这是一个具体的例子:
const generateProps = () => ({foo: 'bar'});
const ParentComponent = () => ({
const someProps = generateProps();
return (
<SomeComponent><ChildComponent {...someProps} otherProp='hello world'/></SomeComponent>
)
})
每次 ParentComponent
渲染时,ChildComponent 都会渲染(对吗?)。我知道你可以做的一件事是用 React.memo
包装 ChildComponent
并对 Prop 进行更深入的比较(将自定义比较函数传递给它),但是什么如果您无法控制 ChildComponent
?你是被迫露骨的吗?还是我不正确,ChildComponent
不会在这个例子中重新呈现(假设 ChildComponent
只是使用 Prop 而不使用任何上下文或任何东西)。
谢谢!
最佳答案
你错了。和解不看 Prop 。主要看组件类型,例如
如果在一个渲染上渲染
<Comp1/>
在下一次渲染时,在组件树中的同一个地方,你渲染:
<Comp2/>
它将卸载Comp1
并挂载Comp2
,因为组件的类型不同。如果组件类型相同,它将更新现有的。还有更多细节,但您可以自己查看。
此外,如果您使用 React.memo
,默认情况下也会以浅层方式比较 props,因此如果在一个渲染上您通过了
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>
关于javascript - 在保持引用相等的同时传播 Prop ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67876724/