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" />
我正在动态生成 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" />