As the project progresses, the page components become more and more detailed. When we setState on the parent component, we may result in invalid render on several child components. So solving this problem is the purpose of our study.

What does shouldComponentUpdate do?

ShouldComponentUpdate lets React know if a change in the current state or property does not affect the output of the component, returns true by default, does not override render when returning false, and is not called when initializing a render or when using forceUpdate. All we have to do is:

shouldComponentUpdate(nextProps, nextState) {
  return this.props.someData === nextProps.someData
}
Copy the code

React gave us the PureComponent

PureComponent

PureComponent is almost identical to Component, but PureComponent implements shouldComponentUpate with a shallow contrast between props and state. If the object contains complex data structures, it may generate false negative judgments due to deep data inconsistencies (represented by the fact that the view of the object’s deep data has been changed but not updated)

import { Component, PureComponent } from 'react'

class Parent extends Component {
  state = {
    title: 'I am the thing that changes'.name: 'Joe'
  }

  handleChangeTitle() {
    this.setState({ title: 'I've changed'})}handleChangeName() {
    this.setState({ name: 'bill'})}render() {
    return (
      <>
        <div onClick={this.handleChangeTitle.bind(this)}>{this.state.title}</div>
        <div onClick={this.handleChangeName.bind(this)}>Change the value of children</div>
        <Child name={this.state.name} />
      </>)}}class Child extends PureComponent {
  render() {
    console.log('child is render.... ')
    return (
      <div>I am the name of the child component: {this.props. Name}</div>)}}Copy the code

When the handleChangeTitle method is fired, the Render method is not fired. When the handleChangeName method is triggered, the render method is fired, perfect, but what if the props passed to the Child are not strings, Number, etc., but complex types like Object?

import { Component, PureComponent } from 'react'

class Parent extends Component {
  state = {
    title: 'I am the thing that changes'.user: { name: 'Joe'}}handleChangeTitle() {
    this.setState({ title: 'I've changed'})}handleChangeName() {
    let { user } = this.state
    user.name = 'bill'
    this.setState({ user })
  }

  render() {
    return (
      <>
        <div onClick={this.handleChangeTitle.bind(this)}>{this.state.title}</div>
        <div onClick={this.handleChangeName.bind(this)}>Change the value of children</div>
        <Child name={this.state.name} />
      </>)}}class Child extends PureComponent {
  render() {
    console.log('child is render.... ')
    return (
      <div>I am the name of the child component: {this.props.user.name}</div>)}}Copy the code

When handleChangeName is triggered, render is not triggered and the interface is not rendered. This is because the reference to the User object in state has not changed. Some say we change the reference to the user in handleChangeName, and PureComponent gets it right.

this.setState({ user: { name: 'bill'}})Copy the code

In our work, most of the objects passed in May look like this: {name: ‘zhang SAN ‘, age: 26, sex:’ nan ‘, work: ‘code animal ‘,… }, this is not a good time to change the reference. So what’s our solution?

immutable.js

Immutable is a type of persistent data. Once created, it cannot be changed. When an IMMUTABLE object is modified, a new IMMUTABLE object is returned without changing the original data. Immutable data implements structure sharing: it only affects the node you are changing and its parent, which is shared by other nodes, thereby saving performance.

import { Component, PureComponent } from 'react'
import { fromJS } from 'immutable'

class Parent extends Component {
  state = {
    title: 'I am the thing that changes'.user: fromJS({ name: 'Joe'})}handleChangeTitle() {
    this.setState({ title: 'I've changed'})}handleChangeName() {
    let { user } = this.state
    user = user.set('name'.'bill')
    this.setState({ user })
  }

  render() {
    return (
      <>
        <div onClick={this.handleChangeTitle.bind(this)}>{this.state.title}</div>
        <div onClick={this.handleChangeName.bind(this)}>Change the value of children</div>
        <Child name={this.state.name} />
      </>)}}class Child extends PureComponent {
  render() {
    console.log('child is render.... ')
    const user = this.props.user.toJS()
    return (
      <>
        <div>I am the name of the child component: {this.props.user.get('name')}</div>
        <div>I am the name of the child component: {user.name}</div>
      </>)}}Copy the code

Happy hacking: immutable: juejin.cn/post/697679…