React深入一丢丢

1.给setState传入回调函数

setState其实是异步的. 因为出于性能优化考虑, React会将多次setState做一次批处理. 于是setState并不会在被调用之后立即改变我们的state. 这就意味着你并不能依赖于在调用setState方法之后立即使用state, 因为此时你并不能确认该state更新与否. 当然针对这个问题我们也有解决办法–用前一个state(previous state)作为需要传入函数的参数,将一个函数作为参数传递给setState. 这样做能保证你传入的函数需要取到的state一定会是被传入的setState执行之后的state.

举个例子就是:

// 不使用callback
state={a:0}
this.setState({a:1})
this.setState({a:2})
console.log(this.state.a) //0
// 使用callback
state={a:0}
this.setState({a:1},()=>console.log(this.state.a)) //1
this.setState({a:2})
console.log(this.state.a) //0
// 传入函数
state={a:0}
this.setState({a:1})
this.setState((nextState, nextProps)=>{
    console.log(nextState.a) //1
})
console.log(this.state.a) //0

2.使用无状态组件

export function UIComponent(props){
    return <div>{props.name}</div>
}

3. 使用高阶组件

export function HOC(WrappedComponent) {
    return class Test extends Component {
      render() {
          const newProps = {
              title: 'New Header',
              footer: false,
              showFeatureX: false,
              showFeatureY: true
          };

          return <WrappedComponent {...this.props} {...newProps} />
      }
    }
}        

4.使用简单索引作为key

通常循环列表的时候都会用数组顺序作为索引的key值,而更好的性能优化是把key和我们想要表达的数据紧紧关联在一起

//bad->会阻碍React对于我们组件的优化,可能传了一个假key
{todos.map((todo, index) =>
    <Todo
        {...todo}
        key={index}
    />
)}
//good -> 保持了对数据的索引
{todos.map((todo) =>
    <Todo {...todo}
    key={todo.id} />
)}

5.shouldComponentUpdate检查

合理的实现shouldComponentUpdate能够避免不必要的重新渲染.
当React想要重新渲染组件时, React会检查shouldComponentUpdate这个函数是返回true还是false(这将决定组件是否更新.)React默认这个函数是返回true的,意味着无论state还是props发生变化, 组件都将被更新). 所以对于那些不需要变化的组件, 我们可以直接返回false来阻止组件更新,以此提升性能. 但更多的时候, 我们需要在这个函数内写自己的逻辑来判断组件是否需要更新.

shouldComponentUpdate(nextProps, nextState) {
   if (nextProps.a !== this.props.a) {
         return true;
   }
   return false;
}

6.使用PureComponent

Pure Component默认会在shouldComponentUpdate方法中做浅比较. 只有PureComponent检测到state或者props发生变化时,PureComponent才会调用render方法,这种实现可以避免发生在state或者props没有真正改变的重新渲染.
Recompose提供了一个叫pure的高阶组件来实现这个功能, React在v15.3.0中正式加入了React.PureComponent.

浅比较只会"浅"检查组件的props和state,这就意味着嵌套对象 和 数组 是不会被比较的。
handleClick() {
    let {items} = this.state
    items.push('new-item')
    this.setState({ items })
}
render() {
    return (
        <div>
              <button onClick={this.handleClick} />
              <ItemList items={this.state.items} />
        </div>
    )
}        

如果ItemList是纯组件(PureComponent),那么这时它是不会被重新渲染的,因为尽管this.state.items的值发生了改变,但是它仍然指向同一个对象的引用(浅比较)