7
头图

join us!

Mountain" , to provide front-end developers with technical information and a series of basic articles. For a better user experience, please move to our official website rookies (160e8020a81dbe https://xhs-rookies.com/ ) to learn and get the latest articles in time.

"Code tailor" , if you are interested in our article or want to make some suggestions, follow "Novices of Xiaohe Mountain" public account, contact us, you can also watch it on WeChat Our article. Every suggestion or approval is a great encouragement to us!

Preface

In this section, we will introduce React in setState , hoping to help everyone really understand setState .

This article will introduce you to the following:

  • How to use setState
  • Cannot directly modify State
  • setState()
  • setState may be an asynchronous update
  • The merger of setState

How to use setState

Before introducing setState , let's take a setState at a case of 060e8020a82202 to understand how it is used.

Let's show a use case, when clicking a button to change the text, modify the content displayed before the interface:

默认展示

Case code

import React, { Component } from 'react'

export default class App extends Component {
  constructor(props) {
    super(props)

    this.state = {
      message: 'Hello React',
    }
  }

  render() {
    return (
      <div>
        <h2>{this.state.message}</h2>
        <button onClick={(e) => this.changeMessage()}>ChangeMessage</button>
      </div>
    )
  }

  changeMessage() {
    this.setState({
      message: 'Hello xhs,your message is changed.',
    })
  }
}

state is set in the class constructor, and then if you want to change state , it is through the setState function, the main thing of this function is to pass in an object as a parameter, and the object is the value you want to modify. In the above code, when you click ChangeMessage setState function will be called, and setState will call the render function, and the page will be re-rendered.

After clicking the button, the effect of re-rendering:

重新渲染之后

Cannot directly modify State

changeMessage above 060e8020a82438 method to the following.

changeMessage() {
  this.state.message = "Hello xhs,your message is changed.";
}

After clicking ChangeMessage , the page does not change, but state you will find that state in message changed, but the page will not be re-rendered.

The constructor is the only this.state , and in order to re-render the page, it can only be modified setState

So, we modify the data setState

  • When we call setState , the re-executes render function, according to the latest State to create ReactElement objects
  • Again according to the latest ReactElement object, DOM be modified;
changeMessage() {
  this.setState({
    message: "Hello xhs,your message is changed."
  })
}

setState()

setState(updater, [callback])

setState() state the changes to the component React needs to re-render this component and its subcomponents with the updated state This is the main way to update the user interface in response to event handlers and process server data

setState() as a request for instead of an immediate component update command. In order to better perceive performance, React will delay calling it, and then update multiple components through one pass. React does not guarantee that state will take effect immediately.

setState() does not always update components immediately. It will postpone updates in batches. This makes it a hidden danger to read this.state setState() In order to eliminate hidden dangers, please use the callback function of componentDidUpdate or setState setState(updater, callback) ), both of which can be guaranteed to be triggered after the application is updated.

Parameter one can have two forms

1. Accepted object type

setState(stateChange[, callback])

stateChange will superficially merge the incoming objects into the new state , for example, let count +1

this.setState({ count: this.state.count + 1 })

This form of setState() is also asynchronous, and multiple setState be batched in the same cycle. count + 1 multiple times in the same cycle, it is equivalent to:

Object.assign(
  previousState, // 之前的状态
  {count: state.count + 1},
  {count: state.count + 1},
  ...
)

setState() called later will cover the value of the first setState called in the same cycle, so the number of commodities will only increase once. If the subsequent state depends on the current state, we recommend using the form of the updater function instead:

this.setState((state) => {
  return { count: state.count + 1 }
})

2. Accept function parameters

In our initial state and not a count . But now we have a requirement: that is to add a count in state , use the object as the first parameter, you will find such a problem.

changeCount () {
    this.setState({
        count: 0
    }) // => this.state.count 是 undefined
    this.setState({
        count: this.state.count + 1
    }) // => undefined + 1 = NaN
    this.setState({
        count: this.state.count + 2
    }) // => NaN + 2 = NaN
}

The results of running the above code does not meet our expectations, we hope count operating results are 3 , but end up with NaN . However, it is not uncommon for this subsequent operation to rely on setState

Here naturally leads to setState , which can accept a function as a parameter. React.js will setState the result of the previous 060e8020a82a6d into this function, you can use the result to perform calculations and operations, and then return an object as the object to state

changeCount () {
    this.setState((prevState) => {
        return { count: 0 }
    })
    this.setState((prevState) => {
        return { count: prevState.count + 1 }
    // 上一个 setState 的返回是 count 为 0,这里需要执行 +1 所以当前返回 1
  })
    this.setState((prevState) => {
        return { count: prevState.count + 2 }
    // 上一个 setState 的返回是 count 为 1,这里需要执行 +2 所以当前返回 3
    })
  // 最后的结果是 this.state.count 为 3
}

In this way, the above-mentioned use the last setState result to perform the effect.

The second parameter is the callback function

setState() is an optional fallback function, which will be setState after 060e8020a82b24 completes the merge and re-renders the components. Generally, we recommend using componentDidUpdate() instead of this method.

Let's add two printing methods to the function changeMessage in the case.

changeMessage() {
  this.setState({
        message: "Hello xhs,your message is changed."
    },() => {
    console.log('callback result: ',this.state.message);
  })
  console.log('no callback result:',this.state.message);
}

Let's see the result

在这里插入图片描述

From the picture we can see

  • When setState , we can’t get the result we want right away
  • callback returns the modified result.

Just because we don't get the result we want right away, this is what we will talk about next. may be an asynchronous update .

In this way, we can know the setState of the second parameter of 060e8020a82d6b, which is to ensure that state has been modified. That is, the content executed after re-rendering.

setState may be updated asynchronously

Let's look at the following code:

  • The final print result is Hello React ;
  • It can be seen that setState is an asynchronous operation, and we cannot get the latest state result setState
changeMessage() {
  this.setState({
    message: "Hello xhs,your message is changed."
  })
  console.log(this.state.message); // Hello React
}

Why is setState designed to be asynchronous?

  • setState designed to be asynchronous. In fact, there have been a lot of discussions GitHub
  • React core members (Redux author) Dan Abramov also has corresponding reply , you can refer to;

Let's make a brief summary of his answer:

  • setState designed to be asynchronous, which can significantly improve performance;
  • If setState is called for an update every time, it means that the render function will be called frequently and the interface will be re-rendered, which is very inefficient;
Note: The is to get multiple updates and then perform batch updates;
  • state updated synchronously render function has not been executed, then state and props cannot be kept synchronized;
Note: state and props cannot maintain consistency, which will cause many problems in the development;

gets the updated value

changeMessage() {
  this.setState({
    message: "Hello xhs,your message is changed."
  }, () => {
    console.log(this.state.message); // Hello xhs,your message is changed.
  });
}

Of course, we can also function in the life cycle:

componentDidUpdate(prevProps, provState, snapshot) {
  console.log(this.state.message);
}

setState must be asynchronous?

Doubt: setState must be updated asynchronously?

Verification 1: Update setTimeout

changeText() {
  setTimeout(() => {
    this.setState({
      message: "你好啊,小和山"
    });
    console.log(this.state.message); // 你好啊,小和山
  }, 0);
}

Verification 2: Native DOM event:

componentDidMount() {
  const btnEl = document.getElementById("btn");
  btnEl.addEventListener('click', () => {
    this.setState({
      message: "你好啊,小和山"
    });
    console.log(this.state.message); // 你好啊,小和山
  })
}

In fact, it is divided into two situations:

  • In the component life cycle or React synthesis event, setState is asynchronous;
  • In the event of setTimeout or native dom setState is synchronous;

Combination of setState

Consolidation of data

When you call setState() , React will merge the object you provided into the current state

Define some data for state

this.state = {
  name: 'xhs',
  message: 'Hello React',
  count: 0,
}

Modifying state in message through setState will not affect name

changeMessage() {
  this.setState({
    message: "Hello xhs,your message is changed."
  });
}

Multiple setState will be merged

For example, we still have a count attribute, the default is 0 , record the current number:

  • After performing the following operations, the final answer is 1
  • Multiple state were merged
increment() {
    this.setState({
        count: this.state.count + 1
    });

  this.setState({
    count: this.state.count + 1
  });

  this.setState({
    count: this.state.count + 1
  });
}

How can it be done so that count will eventually become 3 ?

increment() {
  this.setState((state, props) => {
    return {
      count: state.count + 1
    }
  })

  this.setState((state, props) => {
    return {
      count: state.count + 1
    }
  })

  this.setState((state, props) => {
    return {
      count: state.count + 1
    }
  })
}

The above code is used, setState receives a function as the first parameter to solve this problem, and we can get the result we expect.

Preview of the next section

In this section, we have learned the React in SetState . In the next chapter, we will continue to learn the React of controlled and uncontrolled components in 060e8020a83ff5, so stay tuned!


小和山的菜鸟们
377 声望2.1k 粉丝

每日进步的菜鸟,分享前端学习手册,和有心学习前端技术的小伙伴们互相探讨,一同成长。