首页 文章

React:当父组件重新渲染时,孩子们总是会重新渲染吗?

提问于
浏览
5

据我所知,如果父母组成部分重新出现,那么除非他们实施 shouldComponentUpdate() ,否则其所有子女都将会重新渲染 . 我made an example这似乎不是真的 .

我有3个组件: <DynamicParent/> ,_104477_和 <Child/> . <Parent/> 组件负责渲染 <Child/> 但以不同方式执行此操作 .

<StaticParent/> 的render函数在运行时之前静态声明 <Child/> ,如下所示:

<StaticParent>
    <Child />
 </StaticParent>

<DynamicParent/> 处理在运行时动态接收和呈现 <Child/> ,如下所示:

<DynamicParent>
    { this.props.children }
 </DynamicParent>

<DynamicParent/><StaticParent/> 都有 onClick 个侦听器来更改其状态并在单击时重新渲染 . 我注意到,当单击 <StaticParent/> 时,它和 <Child/> 都被重新渲染 . 但是当我单击 <DynamicParent/> 时,只会重新呈现父项和非 <Child/> .

<Child/> 是一个没有 shouldComponentUpdate() 的功能组件,所以我不会重新渲染 . 有人可以解释为什么会这样吗?我在与此用例相关的文档中找不到任何内容 .

3 回答

  • 1

    我将发布你的实际代码用于上下文:

    class Application extends React.Component {
      render() {
        return (
          <div>
            {/* 
              Clicking this component only logs 
              the parents render function 
            */}
            <DynamicParent>
              <Child />
            </DynamicParent>
    
            {/* 
              Clicking this component logs both the 
              parents and child render functions 
            */}
            <StaticParent />
          </div>
        );
      }
    }
    
    class DynamicParent extends React.Component {
      state = { x: false };
      render() {
        console.log("DynamicParent");
        return (
          <div onClick={() => this.setState({ x: !this.state.x })}>
            {this.props.children}
          </div>
        );
      }
    }
    
    class StaticParent extends React.Component {
      state = { x: false };
      render() {
        console.log("StaticParent");
        return (
          <div onClick={() => this.setState({ x: !this.state.x })}>
            <Child />
          </div>
        );
      }
    }
    
    function Child(props) {
      console.log("child");
      return <div>Child Texts</div>;
    }
    

    在Application渲染中编写此代码时:

    <StaticParent />
    

    提出的是:

    <div onClick={() => this.setState({ x: !this.state.x })}>
        <Child />
     </div>
    

    而实际上,(粗略地)发生的是:

    function StaticParent(props) {
      return React.createElement(
        "div",
        { onClick: () => this.setState({ x: !this.state.x }) },
        React.createElement(Child, null)
      );
    }
    
    React.createElement(StaticParent, null);
    

    当您像这样渲染DynamicParent时:

    <DynamicParent>
        <Child />
    </DynamicParent>
    

    这就是实际发生的事情(粗略地说)

    function DynamicParent(props) {
        return React.createElement(
            "div",
            { 
                onClick: () => this.setState({ x: !this.state.x }), 
                children: props.children 
            }
        );
    }
    
    React.createElement(
          DynamicParent,
          { children: React.createElement(Child, null) },
    );
    

    在这两种情况下,这都是孩子:

    function Child(props) {
        return React.createElement("div", props, "Child Text");
    }
    

    这是什么意思?好吧,在StaticParent组件中,每次调用StaticParent的render方法时,都会调用 React.createElement(Child, null) . 在DynamicParent情况下,Child被创建一次并作为prop传递 . 由于 React.createElement 是一个纯粹的函数,因此可能会在某处为性能而备忘 .

    什么会使Child的渲染在DynamicParent案例中再次运行是Child的道具的变化 . 例如,如果将父级的状态用作Child的prop,则会在两种情况下触发重新呈现 .

    我真的希望丹·阿布拉莫夫没有出现在评论上,以摒弃这个答案,写作是一种痛苦(但很有趣)

  • 5

    这主要是因为你有两个不同的“孩子” .

    • this.props.children

    • <Child/>

    它们不是同一个东西,第一个是 propApplication -> DynamicParent 向下传递,而第二个是在 StaticParent 中渲染的 Component ,它们具有单独的渲染/生命周期 .

    你包含的例子

    class Application extends React.Component {
      render() {
        return (
          <div>
            {/* 
              Clicking this component only logs 
              the parents render function 
            */}
            <DynamicParent>
              <Child />
            </DynamicParent>
    
            {/* 
              Clicking this component logs both the 
              parents and child render functions 
            */}
            <StaticParent />
          </div>
        );
      }
    }
    

    字面意思如下:

    class Application extends React.Component {
      render() {
        // If you want <Child/> to re-render here
        // you need to `setState` for this Application component.
        const childEl = <Child />;
        return (
          <div>
            {/* 
              Clicking this component only logs 
              the parents render function 
            */}
            <DynamicParent>
              {childEl}
            </DynamicParent>
    
            {/* 
              Clicking this component logs both the 
              parents and child render functions 
            */}
            <StaticParent />
          </div>
        );
      }
    }
    
  • -2

    它只会重新渲染已经发生变化的组件 . 如果子组件上没有任何内容发生更改,则不会重新呈现 .

相关问题