What is an immutable value

Functional programming means that functions and expressions in a program can be given input values and output is deterministic, just like functions in mathematics. Such as

let a = 1;
let b = a + 1;
=> a = 1  b = 2;
Copy the code

Variable B appears, although the value of variable A is used, but the value of a is not modified.

This. State = {count: 1}

componentDidMount() { const newState = { ... state, count: 2 }; // { count: 2 } this.setState(newState); }Copy the code

Although we used this.state, we didn’t change the reference address of this.state or the value of count directly, and we did the same for this.props.

Why immutable values

React offers three benefits:

  • Simplify complex functions

    Immutability makes complex features easier to implement.

  • Track changes in data

    If you modify the data directly, it is difficult to track the changes. Tracking data changes requires that the mutable object can be compared to the previous version, so that the entire object tree needs to be traversed once.

    It is relatively easy to track changes in immutable data. If the object becomes a new object, we can say that the object has changed.

  • Determine when to rerender in React

    The main advantage of immutability is that it helps us create pure Components in React. We can easily determine if immutable data has changed and thus when to rerender the component.

React performance optimization requires immutable values

  • First, we all know that the shouldComponentUpdate hook function returns true by default, that is, whenever the parent component is updated, the child component must be updated.

  • ShouldComponentUdpate can accept two parameters, nextProps and nextState, XXX is equal to nextProps. XXX, and this.state. XXX is equal to nextstate. XXX.

class CounterButton extends React.Component { constructor(props) { super(props); this.state = {count: 1}; } shouldComponentUpdate(nextProps, nextState) { if (this.props.color ! == nextProps.color) { return true; } if (this.state.count ! == nextState.count) { return true; } return false; } render() { return ( <button color={this.props.color} onClick={() => this.setState(state => ({count: state.count + 1}))}> Count: {this.state.count} </button> ); }}Copy the code
  • React V15.3 adds a new PureComponent class that shallow compares props to state to reduce the number of times the render function is executed, avoiding unnecessary component rendering and optimizing performance.

  • How does PureComponent work

    As we know, variable types in JS are divided into basic types (number, String, Boolean, undefined, NULL, symbol) and reference types (function, object, function). Values of basic types are stored in stack memory. The values of reference types are stored in heap memory, and only references to heap memory are stored in stack memory. Shallow comparisons, on the other hand, only compare data in stack memory.

class App extends PureComponent {
  state = {
    items: [1, 2, 3]
  }
  handleClick = () => {
    const { items } = this.state;
    items.pop();
    this.setState({ items });
  }
  render() {
    return (
        <div>
            <ul>
                {this.state.items.map(i => <li key={i}>{i}</li>)}
            </ul>
            <button onClick={this.handleClick}>delete</button>
        </div>
    )
  }
}
Copy the code

The above example uses PureComponent and only changes the items array, not the reference address of the items. Therefore, items are not changed and the render function does not trigger the component.

If you want to implement component updates, you can create a new array as follows and assign the address of the new array to Items.

handleClick = () => {
    const { items } = this.state;
    items.pop();
    var newItem = [...items];
    this.setState({ item: newItem });
}
Copy the code
  • PureComponent does a shallow comparison for us, so be careful with state, and use Immutable. Js if you need data structures that refer to nested references.

  • What is Immutable

(1) Immutable is data that, once created, cannot be changed. (2) Any modification or addition or deletion of an Immutable object returns a new Immutable object. (3)Immutable Data structures are Persistent Data structures, which ensure that old Data is available and unchangeable at the same time when creating new Data. (4) Immutable uses Structural Sharing to avoid performance loss caused by deepCopy copying all nodes at once. Immutable uses Structural Sharing, which means that when a node in the object tree changes, only the node and its affected parent are modified, and the other nodes are shared.

  • Finally, if you want a shallow comparison at the component level, you can use the react.Memo () function

conclusion

  1. The third and most important advantage of immutability is that immutability allows us to use PureComponent in React. We can easily determine if the data has changed and when the component needs to be rerendered.

  2. If we change state, shouldComponentUpdate returns false if it compares the current state to nextState, or if it compares the props to nextProps, even if we did setState. The UI will not be updated.

  3. PureComponent is best used with Immutable. Js for performance optimization purposes.

  4. Combine React. Memo to avoid unnecessary component updates to render.

Refer to the article

Part of this article has been adapted from the following articles:

React ShouldComponentUpdate with immutable values

React Component Performance Optimization (PureComponent)

Use immutable to optimize React

Why is immutability important to React?