This article mainly discusses the design philosophy of React State and summarizes the usage of setState.

1 One definition of State:

State can be thought of as a collection of mutable State data in a React component’s UI.

Mutable state data is data that can be modified (or updated) in the current component.

If we want to define a variable in a component, how do we determine whether it is appropriate to use that variable as a State?

2 Component State requirements:

  • State must be the complete set of states represented by a component’S UI: any changes to the component’s UI can be reflected by changes in State.
  • State must be the minimum set of states that represent the presentation of a component’S UI: all states in State are used to reflect changes to the component’s UI, without any redundant states or intermediate states that need to be computed from other states.

As you can see, the first requirement is “complete” and the second requirement is “minimum”.

3 Whether the variable can be used as the criterion of State:

Whether a variable used in a component should be used as a component State can be determined by the following four criteria:

1. Is this variable fetched from the parent component via Props? If so, it is not appropriate to represent it as State.

2. Does this variable remain constant throughout the life of the component? If so, it is not appropriate to represent it as State.

3. Can this variable be evaluated by other states or properties (Props)? If so, it is not appropriate to represent it as State.

4. Is this variable used as data in the render method? If not, it is not appropriate to represent it as State. In this case, it is better to define the variable as a common property of the component. For example, the timer used in the component should be defined as this.timer instead of this.state.timer.

5. Also consider whether the state needs to be promoted to the parent component.

4 The difference between State and Props:

State is mutable in the current component to meet the needs of component UI changes;

Props is read-only for child components.

5 How do I change State correctly?

5.1 Do not assign state directly

This.state.com = 'Hello'; this.state.com = 'Hello'; this.state.com = 'Hello';Copy the code

Such a direct assignment is only allowed when State is initialized in the component’s constructor; Most of the other times, you should use setState(), which we’ll cover in more detail at the end of this article:

// Correct: this.setstate ({comment: 'Hello'});Copy the code

5.2 Updates to State can be asynchronous

React can be multiplesetState()Calls are consolidated into one call to improve performance. The same is true for the Props update mechanism. This is called “asynchronous updating”.

becausethis.propsandthis.stateThey may be asynchronously updated, and you should not rely on their values to calculate the next state.

5.2.1 Remedy this deficiency:

We can’t get the latest state of the props and state directly from this.state and this.props, but in this.setState, the latest state of the state and props can be obtained from a callback function:

SetState ((preState, props) => ({counter: prestate. quantity + 1 + props. }))Copy the code

PreState, the first argument to the above callback, captures the last State; The second parameter captures the latest props.

5.3 Updating State is a shallow merge process

When setState is called to modify the State of a component, only the changed State is passed in, not the complete State of the component, because the update of the component State is a Shallow Merge. For example, a component initializes in the following state:

this.state = {
  title : 'React',
  content : 'React is an wonderful JS library!'
}Copy the code

If you only need to change the title, you should:

this.setState({title: 'Reactjs'});Copy the code

React merges the new title into the original component State while retaining the original content State.

{
  title : 'Reactjs',
  content : 'React is an wonderful JS library!'
}Copy the code

5.4 The State and Immutable

React officially recommends treating State as an immutable object. That is, when you feel the urge to change the value of this. State, what you should do is create a new value to assign to this. State.

So how do you do that? Let’s break it down a bit more:

5.4.1 The usual assignment:

Applicable types are: numbers, strings, Booleans, null, undefined. See examples:

this.setState({
  count: 1,
  title: 'Redux',
  success: true
})Copy the code

5.4.2 The value of a state is of type array

If you have a state books of array type, use the concat method of array or ES6’s spread syntax when adding a book to books:

Var books = this.state. Books; var books = this.state. this.setState({ books: books.concat(['React Guide']); This.setstate (preState => ({books: prestate.books.concat (['React Guide'])); SetState (preState => ({books: [...preState. Books, 'React Guide']; }))Copy the code

Use the slice method of arrays when snatches elements from books as new states. (Same with arrays returned by splice.)

Var books = this.state. Books; Enclosing setState ({books: books. Slice (1, 3); }) this.setstate (preState => ({books: prestate.books.slice (1,3); }))Copy the code

When some elements are filtered from books as new states, use the filter method of the array:

Var books = this.state. Books; this.setState({ books: books.filter(item => { return item ! = 'React'; }); SetState (preState => ({books: prestate.books. filter(item => {return item! = 'React'; }); }))Copy the code

Do not use push, POP, shift, unshift, etc., to change the state of the array type, because these methods are based on the original array, while concat, Slice, splice, filter can return a new array.

5.4.3 The value of the state is a normal object (excluding strings, arrays).

Use ES6’s Object.assgin method

Var owner = this.state.owner; var owner = this.state.owner; var owner = this.state. this.setState({ owner: Object.assign({}, owner, {name: 'Jason'}); This.setstate (preState => ({owner: object.assign ({}, prestate. owner, {name: object.assign ({}, preState. 'Jason'}); }))Copy the code

Using object Spread Properties syntax:

Var owner = this.state.owner; var owner = this.state.owner; this.setState({ owner: {... owner, name: 'Jason'}; SetState (preState => ({owner: {... preState.owner, name: 'Jason'}; }))Copy the code

5.4.4 Why is the state of the recommended component immutable?

On the one hand, immutable objects are easy to manage and debug. See here for more information. On the other hand, for the sake of performance, when object component states are immutable objects, we can determine whether the state really changes only by comparing the reference of the state in the component shouldComponentUpdate method, so as to avoid unnecessary render calls. When we use the React PureComponent, we need to ensure that the component state is immutable. Otherwise, the state comparison in the component’s shouldComponentUpdate method can be wrong because PureComponent performs shallow comparisons (comparing references to objects).

6 Various ways of writing setState:

In the previous chapter of this article, “How to Change State correctly,” we looked at the various rules, along with a glimpse of setState. Let’s dig a little deeper into the different ways of writing setState, and the differences between them.

As we said earlier, State updates can be asynchronous:

SetState queues state changes in a component and tells the component and its children that they need to be rerendered with the updated state. This is the most common way to update the UI in the Event Handlers function or server Responses function.

We should think of setState as a request rather than an immediate command to update the component. For better performance, React might collect setState requests several times and then update the State once again. Or React might delay updating State.

So if setState is called and this.state. XXX is used to obtain the value of state, React does not guarantee immediate results.

If some of your scripts must be executed after the State update, you can either write the code in componentDidUpdate or use the setState callback (updater, callback).

6.1 And by the way, the setState and thePage rerenderingThe relationship between:

My summary is as follows:

  • SetState always triggers a rerendering of the page.
  • If false is returned in shouldComponentUpdate when setState is called, rerendering is not triggered.
  • When setState is called, updating the state of mutable objects (mutable objects as opposed to immutable objects) does not trigger rerendering.

Their principle is that rerendering is triggered only if the new state is different from the previous state, in order to reduce unnecessary rendering.

6.2 SetState can be written in two ways:

SetState can be written in two ways:

  1. setState(updater[, callback])The first argument is an updater function; The second argument is a callback function (optional)
  2. setState(stateChange[, callback])The first argument is an object; The second parameter is the same as above (optional)

The second argument, all the same, is an optional callback function that will be executed after setState has been executed and the component has been redefined. In general, we recommend using componentDidUpdate for this kind of logic.

6.2.1 The first argument is the updater function; The second argument callback function is less used and omitted

Examples are as follows:

this.setState((prevState, props) => {
  return {counter: prevState.counter + props.step};
});Copy the code

As mentioned above, both preState and Props have access to the latest data without further details. The updater function usually returns an object!

6.2.2 The first argument is the object; The second argument callback function is less used and omitted

Examples are as follows:

this.setState({quantity: 2})Copy the code