React--shouldComponentUpdate

shouldComponentUpdate 作用

官方文档:https://react.docschina.org/docs/optimizing-performance.html

使用方式:

class Hello extends React.Component {

  shouldComponentUpdate(nextProps, nextState) {
    if (nextProps.greeting !== this.props.greeting) return true
    if (nextState.name !== this.state.name) return true
    return false
  }

  state = {
    name: 'Hello Class Component'
  }

  handleClick () {
    this.setState({
      name: 'Update - ' + this.state.name
    })
  }

  render() {
    console.log('Hello render')
    return (
      <>
        <h1>{this.props.greeting}</h1>
        <h2>{this.state.name}</h2>
        <button onClick={() => this.handleClick()}>Update State Name</button>
      </>
    )
  }
}

该钩子函数会在props或者state更新之后回调,传递两个参数为:更新后的props、更新后的state
返回一个boolean

  • true:当前组件及其子组件执行渲染逻辑
  • false该组件及其子组件都不需要重新计算渲染

React.PureComponent 纯组件

类组件继承React.PureComponent时,就相当于以上添加了shouldComponentUpdate钩子函数的渲染优化
需要注意的是,该函数执行的比较是浅比较(也应该要是浅比较,深度比较太消耗性能),所以某些情况的赋值逻辑需要注意

示例:

import React from "react";

class HobbiesList extends React.PureComponent {

  componentDidUpdate() {
    console.log('HobbiesList componentDidUpdate')
  }

  render () {
    return (
      <>
        <ul>
          {this.props.hobbies.map(h => <li key={h.id}>{h.name}</li>)}
        </ul>
      </>
    )
  }
}

export default class Home extends React.Component {

  constructor (props) {
    super(props)
    this.state = {
      currentId: 2,
      hobbies: [
        {id: 0, name: '吃饭'},
        {id: 1, name: '睡觉'},
        {id: 2, name: '打王者'},
      ],
      inputVal: '',
    }
    this.handleInput = this.handleInput.bind(this)
    this.addHobby = this.addHobby.bind(this)
  }

  handleInput (e) {
    this.setState({
      inputVal: e.target.value
    })
  }

  addHobby () {
    const hobbies = this.state.hobbies
    const newID = this.state.currentId + 1
    const newName = this.state.inputVal

    hobbies.push({
      name: newName,
      id: newID,
    })
    this.setState({
      hobbies,
      currentId: newID,
    })
  }

  render () {
    return (
      <>
        <input value={this.state.inputVal} onInput={this.handleInput} />
        <button onClick={this.addHobby}>添加爱好</button>
        <HobbiesList hobbies={this.state.hobbies} />
      </>
    )
  }
}

代码说明:

  1. HobbiesList是用户渲染爱好列表数据的组件,接收Home组件传递的hobbies属性作为数据源;
  2. Home组件中可以向hobbies添加数据,修改hobbies的状态
  3. props变化HobbiesList重新渲染

如果HobbiesList继承的是React.Component,那么,当父级组件有某一个它不需要的状态更新了了,比如Homestate中的currentId,该属性仅在Home组件中使用,并没有传递给HobbiesList,但是,currentId单独更新的时候,所有的组件还是会执行一次render函数、componentDidUpdate等钩子函数,非常消耗性能

说回代码执行情况,当点击【添加爱好】按钮时,会执行以下的逻辑:

addHobby () {
    const hobbies = this.state.hobbies
    const newID = this.state.currentId + 1
    const newName = this.state.inputVal

    hobbies.push({
      name: newName,
      id: newID,
    })
    this.setState({
      hobbies,
      currentId: newID,
      inputVal: ''
    })
  }

但是,HobbiesList组件并不会像想象之中那样更新

因为,HomesetState()方法更新的hobbies数组还是原来的地址,而HobbiesList继承了纯组件,会在shouldComponentUpdate钩子函数中进行props的浅比较,当发现数组(或者对象)的引用值地址一致,就会直接返回false,也就不会刷新组件了

所以,应该在父级更新状态时调整一下:

addHobby () {
    const hobbies = this.state.hobbies
    const newID = this.state.currentId + 1
    const newName = this.state.inputVal
    
    this.setState({
      hobbies: [...hobbies, {
        name: newName,
        id: newID,
      }],
      currentId: newID,
      inputVal: '',
    })
  }

使用扩展运算符,并使用了一个新数组设置了状态,子组件就能够更新了

小结

  • shouldComponentUpdate可以用于性能优化,通过返回一个boolean值,指导组件是否重新渲染。但是,也仅用于性能优化,不要特地阻止组件刷新,否则会导致意外的 bug
  • 类组件可以继承React.PureComponent纯组件,可以省下shouldComponentUpdate钩子函数的编写,进行的是浅比较,需要注意状态更新的赋值方式
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值