【问题标题】:Children in Parent Functional Component are not Re-rendering on Props Change父功能组件中的子级不会在道具更改时重新渲染
【发布时间】:2021-08-27 08:49:14
【问题描述】:

我正在动态生成 HOC 父级的子组件(见下文)。我将道具直接传递给其中一个孩子并将道具放入其中。我希望看到孩子在道具上重新渲染会发生变化,但事实并非如此。

代码不正确吗?

ParentComponent

...
const ParentComponent = ({children}) => {
   const [state1, setState1] = useState(true);

   ...

   const changeOpacity = event => setState1(!state1);

   const renderChildren = React.useCallback(() => React.Children.toArray(children).map((child, index) => (
      <div key={index} style={{opacity: `${state1 ? 0 : 1}`}}>
         {child}
      </div>
   )), [state1]);

   return (
      <div>
         <Button onClick={changeOpacity}>Toggle Opacity</Button>
         {renderChildren()}
      </div>
   );
};

App.js

...
const App = () => {
   const [prop1, setProp1] = useState(123);

   return (
      <ParentComponent>
         <Child1 prop1={prop1} setProp1={setProp1} />
         <Child2 />
      </ParentComponent>
   ); 
};

【问题讨论】:

  • 那不是因为你的state1没有改变,所以你得到了renderChildren的momoized?如果你跳过useCallback()会发生什么?
  • 子级仅在单击“切换不透明度”按钮时重新渲染。因为 renderChildren 依赖于 state1 而没有别的
  • 嗯...我认为子组件的渲染与 state1 突变无关,当它的道具发生变化时。但是,是的,删除 useCallback 钩子就可以了。

标签: reactjs react-hooks react-hoc


【解决方案1】:

在您的ParentComponent 中,children 被克隆,然后用作 renderChildren 函数返回值的一部分。由于计算子组件的逻辑不会在道具更改为子组件时运行,因此您的子组件不会受到其道具更改的影响。

您可以将children 依赖添加到useCallback,它会正常工作。

const { useState, useCallback } = React;
const ParentComponent = ({children}) => {
   const [state1, setState1] = useState(true);


   const changeOpacity = event => setState1(!state1);

   const renderChildren = useCallback(() => React.Children.map(children, (child, index) => (
      <div key={index} style={{opacity: `${state1 ? 0 : 1}`}}>
         {child}
      </div>
   )), [children, state1]);

   return (
      <div>
         <button onClick={changeOpacity}>Toggle Opacity</button>
         {renderChildren()}
      </div>
   );
};
const Child1 = ({prop1, setProp1}) => <div>{prop1} <button onClick={() => setProp1(234)}>Click</button></div>;
const Child2 = () => <div>Hello</div>
const App = () => {
   const [prop1, setProp1] = useState(123);

   return (
      <ParentComponent>
         <Child1 prop1={prop1} setProp1={setProp1} />
         <Child2 />
      </ParentComponent>
   ); 
};

ReactDOM.render(<App />, document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id="app" />

【讨论】:

  • 是的,children 依赖使它工作。但我之前的想法是,无论state1,当它的道具发生变化时,孩子都会重新渲染。我使用钩子夸大了逻辑。最好只在父级频繁重新渲染并且每次都渲染子级时才使用它。
  • 是的,没错。如果你的父组件不经常渲染,你也可以避免 useCallback
【解决方案2】:

有什么阻止你采取下面的方法;

const ParentComponent = ({children}) => {
   const [state1, setState1] = useState(true);

   ...

   const changeOpacity = event => setState1(!state1);

   const renderChildren = useCallback(() => React.Children.toArray(children).map((child, index) => (
      <div key={index}>
         {child}
      </div>
   )), [children]);

   return (
      <div>
         <Button onClick={changeOpacity}>Toggle Opacity</Button>
         {state1 && renderChildren()}
      </div>
   );
};

【讨论】:

    猜你喜欢
    • 2023-02-15
    • 1970-01-01
    • 2020-01-15
    • 2021-12-22
    • 1970-01-01
    • 2018-12-28
    • 2020-10-21
    • 2020-05-01
    • 2021-09-01
    相关资源
    最近更新 更多