javascript - 在保持引用相等的同时传播 Prop

标签 javascript reactjs

想象一下,我有一个动态生成组件的一些 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 没有改变,因为 ab 具有相同的值。 您可以在此处验证,单击 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/

相关文章:

Javascript 在页面重新加载时运行

javascript - 使用 jQuery 的 DOM 下拉列表

javascript - 底部带有 Highcharts 的图例

今天的 javascript-being-dumb 体验

javascript - 为什么我们需要 force.on ('tick' .. 在 d3

javascript - 如何在 React 函数之间共享状态并根据更改重新渲染

node.js - 将 google-cloud 与 webpack 集成时出现问题

javascript - 如何向子组件添加事件?

javascript - Chrome 加载第一个 AJAX 响应很慢

reactjs - 如何在 chartjs 中跳过多线图中一行的标签?