【问题标题】:execute only if the children are different in componentDidUpdate仅当子组件在 componentDidUpdate 中不同时才执行
【发布时间】:2020-02-25 14:42:34
【问题描述】:

我需要比较 prevProps 的子元素和当前的 props 并且只在它们在 componentDidUpdate 方法中不同时才执行代码。

当孩子是对象数组时,我如何比较它们?

componentDidUpdate(prevProps) {
  if(!_.isEqual(prevProps.children, this.props.children)) {
   console.log('not equal');
   // execute some code
}

【问题讨论】:

    标签: javascript arrays reactjs children react-props


    【解决方案1】:

    您可以像这样简单地使用常规相等运算符:

    componentDidUpdate(prevProps) {
        if (prevProps.children !== this.props.children) {
            console.log('not equal');
        }
    }
    

    这就是 react 文档所说的。但是请注意,这只会检查数组是否不同。它不会检测数组中的对象是否已更改,但由于 react 的工作原理,它是可以接受的。

    【讨论】:

    • 我猜它不会比较嵌套对象?
    • 当然,但是如果孩子发生变化,react 会将新的孩子数组分配给组件道具。
    【解决方案2】:

    您可以使用=== 来比较子级,但如果您需要执行昂贵的计算或在 props.children 不同时导致重新渲染很多,您可以在父级中记住子级,这样您就不会这样做除非孩子真的变了:

    function App() {
      const [children, setChildren] = React.useState([
        { id: 0, name: 'one' },
        { id: 1, name: 'two' },
      ]);
      const [, setUnRelated] = React.useState({});
      const addChild = () =>
        setChildren(children =>
          children.concat({
            id: children.length,
            name: 'new child',
          })
        );
      const Children = React.useMemo(
        () => children.map(c => <Child key={c.id} {...c} />),
        [children]
      );
      console.log('parent rendering');
      return (
        <div>
          <button onClick={addChild}>Add child</button>
          <button onClick={() => setUnRelated({})}>
            Unrelated change
          </button>
          <ChildList>{Children}</ChildList>
        </div>
      );
    }
    class ChildList extends React.PureComponent {
      componentDidUpdate(prevProps) {
        if (prevProps.children !== this.props.children) {
          console.log('Children in child list not equal');
        }
      }
      render() {
        return this.props.children;
      }
    }
    
    const Child = React.memo(function Child({ id, name }) {
      const rendered = React.useRef(0);
      rendered.current++;
      return (
        <div>
          Rendered {rendered.current} times for: {name} id: {id}
        </div>
      );
    });
    
    ReactDOM.render(<App />, document.getElementById('root'));
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
    <div id="root"></div>

    【讨论】:

      猜你喜欢
      • 2020-01-10
      • 2021-02-12
      • 2020-01-12
      • 2014-04-23
      • 2015-09-09
      • 1970-01-01
      • 2017-12-22
      • 2019-07-19
      • 1970-01-01
      相关资源
      最近更新 更多