什麼是 Impure Component

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

import React, { Component } from react;nimport shallowequal from shallowequal;nnclass FullName extends Component {n shouldComponentUpdate(nextProps) {n return !shallowequal(this.props, nextProps)n }nn render() {n const { firstName, lastName } = this.props;nn return (n <div>{firstName} {lastName}</div>n )n }n}n

React 官方也提供了 PureRenderMixin (給 React.createClass 用)和 React.PureComponent 來讓我們方便地聲明一個 Pure Component。

那麼既然有 Pure Component 的說法,肯定還有相對的 Impure Component。一言以蔽之,只要你的組件依賴了 props 和 state 之外的數據,你的組件就不是 pure 的,我們來看例子。

例子一

class FullName extends Component {n render() {n const { firstName, lastName } = this.props;nn return (n <div>{firstName} {lastName} - {new Date}</div>n )n }n}n

我們在這裡增加了一個當前日期的顯示,導致即使 firstName 和 lastName 不變化,組件每次 render 的結果也是不同的,這個組件就沒辦法用 shouldCompoentUpdate 去優化了。

例子二

class App extends Component {n state = {n lastName: ,n }nn handleChange = e => {n this.setState({ lastName: e.target.value });n }nn renderLastName = () => {n return this.state.lastName;n }nn render() {n <div>n <input type="text" onChange={this.handleChange} />n <FullName firstName="Ava" lastName={this.renderLastName} />n </div>n }n}nnnclass FullName extends Component {n render() {n const { firstName, lastName } = this.props;nn return (n <div>{firstName} {lastName()}</div>n )n }n}n

這個例子我們把 lastName 變成一個方法傳進來,這樣其實 FullName 組件通過閉包,而不是通過 props,依賴了 App 的 state.lastName ,導致在 firstName 和 lastName 都不變化的情況下,FullName 會根據 state.lastName 的不同 render 出不同的結果。

例子三

class App extends Component {n static childContextTypes = {n firstName: React.PropTypes.string,n lastName: React.PropTypes.string,n }nn getChildContext() {n return {n firstName: Taylor,n lastName: Swift,n };n }nn render() {n <Segment>n <FullName />n </Segment>n }n}nnclass Segment extends Component {n render() {n <div>{this.props.children}</div>n }n}nnclass FullName extends Component {n static contextTypes = {n firstName: React.PropTypes.string,n lastName: React.PropTypes.string,n };nn render() {n const { firstName, lastName } = this.context;nn return (n <div>{firstName} {lastName}</div>n )n }n}n

這個例子其實算是 React 留給我們的一個坑(How to implement shouldComponentUpdate with this.context? · Issue #2517 · facebook/react · GitHub),這裡 FullName 是 Pure Component,但是 Segament 卻不是,因為 Segament 的 render 結果間接地依賴了上層的 context。

推薦閱讀:

ReactNative的優質替代品 —— NativeScript 簡介
Python同步谷歌Webfont
【譯】如何學習V8開發
前端與SQL
每周一書-《Bootstrap基礎教程》

TAG:前端开发 | React |