什么是 Impure Component

在优化 React 组件的时候我们常常会看到 Pure Component 的说法,所谓 Pure Component 就是在 props,state 和 context 不变的情况下,组件的 render 结果也是不变的。基于这个前提,我们可以很方便地用 shouldCompoentUpdate 来优化组件,减少 render。

import React, { Component } from 'react';
import shallowequal from 'shallowequal';

class FullName extends Component {
  shouldComponentUpdate(nextProps) {
    return !shallowequal(this.props, nextProps)
  }

  render() {
    const { firstName, lastName } = this.props;

    return (
      <div>{firstName} {lastName}</div>
    )
  }
}

React 官方也提供了 PureRenderMixin (给 React.createClass 用)和 React.PureComponent 来让我们方便地声明一个 Pure Component。

那么既然有 Pure Component 的说法,肯定还有相对的 Impure Component。一言以蔽之,只要你的组件依赖了 props 和 state (context 比较特殊,后面会讲到)之外的数据,你的组件就不是 pure 的,我们来看例子。

例子一

class FullName extends Component {
  render() {
    const { firstName, lastName } = this.props;

    return (
      <div>{firstName} {lastName} - {new Date}</div>
    )
  }
}

我们在这里增加了一个当前日期的显示,导致即使 firstName 和 lastName 不变化,组件每次 render 的结果也是不同的,这个组件就没办法用 shouldCompoentUpdate 去优化了。

例子二

class App extends Component {
  state = {
    lastName: '',
  }

  handleChange = e => {
    this.setState({ lastName: e.target.value });
  }

  renderLastName = () => {
    return this.state.lastName;
  }

  render() {
    <div>
      <input type="text" onChange={this.handleChange} />
      <FullName firstName="Ava" lastName={this.renderLastName} />
    </div>
  }
}


class FullName extends Component {
  render() {
    const { firstName, lastName } = this.props;

    return (
      <div>{firstName} {lastName()}</div>
    )
  }
}

这个例子我们把 lastName 变成一个方法传进来,这样其实 FullName 组件通过闭包,而不是通过 props,依赖了 App 的 state.lastName ,导致在 firstName 和 lastName 都不变化的情况下,FullName 会根据 state.lastName 的不同 render 出不同的结果。

例子三

class App extends Component {
  static childContextTypes = {
    firstName: React.PropTypes.string,
    lastName: React.PropTypes.string,
  }

  getChildContext() {
     return {
       firstName: 'Taylor',
       lastName: 'Swift',
     };
  }

  render() {
    <Segment>
      <FullName />
    </Segment>
  }
}

class Segment extends Component {
  render() {
    <div>{this.props.children}</div>
  }
}

class FullName extends Component {
  static contextTypes = {
    firstName: React.PropTypes.string,
    lastName: React.PropTypes.string,
  };

  render() {
    const { firstName, lastName } = this.context;

    return (
      <div>{firstName} {lastName}</div>
    )
  }
}

这个例子其实算是 React 留给我们的一个,这里 FullName 是 Pure Component,但是 Segament 却不是,因为 Segament 的 render 结果间接地依赖了上层的 context。

    原文作者:yesmeck
    原文地址: https://segmentfault.com/a/1190000007399152
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞