Children Parent 功能组件未 Re-rendering 道具更改

Children in Parent Functional Component are not Re-rendering on Props Change

我正在动态生成 HOC parent 的 children 组件(见下文)。我将道具直接传递给 children 之一并在其中设置道具。我希望看到 child re-rendering 道具改变,但它没有。

代码哪里不对?

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>
   ); 
};

是否有什么阻碍您采用以下方法;

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>
   );
};

在您的 ParentComponent 中,children 被克隆,然后作为来自 renderChildren 函数的 return 值的一部分进行渲染。由于计算子项的逻辑不是 运行 对子项的道具更改,因此您的子组件不受其道具更改的影响。

您可以将 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" />