什麼是 Impure Component

在優化 React 組件的時候咱們經常會看到 Pure Component 的說法,所謂 Pure Component 就是在 props,state 和 context 不變的狀況下,組件的 render 結果也是不變的。基於這個前提,咱們能夠很方便地用 shouldCompoentUpdate 來優化組件,減小 render。react

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。git

那麼既然有 Pure Component 的說法,確定還有相對的 Impure Component。一言以蔽之,只要你的組件依賴了 props 和 state (context 比較特殊,後面會講到)以外的數據,你的組件就不是 pure 的,咱們來看例子。github

例子一

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。this

相關文章
相關標籤/搜索