Posts React setState
Post
Cancel

React setState

最近看到一些文章关于setState的用法,在这里做一个笔记。

setState不为人知的参数

第一个参数:不仅能接受一个对象,还能接受一个函数

该函数接受该组件前一刻的 state 以及当前的 props 作为参数,计算和返回下一刻的 state:

1
2
3
4
5
this.setState(function (state, props) {
 return {
  score: state.score - 1
 }
});

第二个参数:返回当前计算后的state状态

1
2
3
4
5
handle() {
    this.setState((prevState) => ({ count: prevState.count + 1 }), () => {
        console.log(this.state)
    })
}

setState是同步还是异步?

作为一个react初学者,看过一些文章之后我才发现setState是有异步和同步的区分的,所以如果没有很深入的去研究一个框架,很多东西你学会的也是表面的。

生命周期中的setState

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class App extends Component {
  state={
    count:0
  }
  componentDidMount(){
    this.setState((prevState) =>({
      count:prevState.count+1
   }),()=>{console.log("setState",this.state)} // 后输出 setState {count: 1}
   )
   console.log(this.state) // 先输出 {count: 0}
  }
  render() {
    return (
      <div className="App">
        <button>{this.state.count}</button>
      </div>
    );
  }
}

React引发的事件,如onClick/onChange

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 state={
    count:0
  }
  handle = () => {
    this.setState((prevState) =>({
       count:prevState.count+1
    }),()=>{console.log("setState",this.state)} // 输出修改后的值
    )
    console.log(this.state) // 输出上一个state的
  }
  render() {
    return (
      <div className="App">
        <button onClick={this.handle}>{this.state.count}</button>
      </div>
    );
  }

原生事件的setState:通过addEventListener添加的事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
state={
    count:0
  }
  handle = () => {
    this.setState((prevState) =>({
       count:prevState.count+1
    }),()=>{console.log("setState",this.state)} // 两次输出一致,都是修改后的state值
    )
    console.log(this.state) // 两次输出一致,都是修改后的state值
  }
  componentDidMount(){
    document.getElementById('myBtn').addEventListener('click',this.handle)
  }
  render() {
    return (
      <div className="App">
        <button id='myBtn'>{this.state.count}</button>
      </div>
    );
  }

setTimeout/setInterval中的setState

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 state={
    count:0
  }
  componentDidMount(){
    setTimeout(()=>{
      this.setState({
        count:this.state.count+1
      })
      console.log("1",this.state)// 修改后的state值 {count: 1}
    },1000)
    console.log("2",this.state) // {count: 0}
  }
  render() {
    return (
      <div className="App">
        <button id='myBtn'>{this.state.count}</button>
      </div>
    );
  }

setState的批量合并

看到一些文章说setState遇到批量更新的会合并,,其实,是分以下两种写法的

1
2
3
4
  this.setState({ count: this.state.count + 1 })
  this.setState({ count: this.state.count + 1 })
  this.setState({ count: this.state.count + 1 })
  // 这种情况是会合并且只执行最后一次
1
2
3
4
  this.setState((prevState) => ({ count: prevState.count + 1 }))
  this.setState((prevState) => ({ count: prevState.count + 1 }))
  this.setState((prevState) => ({ count: prevState.count + 1 }))
  // 这种情况是输出的值是三次累加的结果

例子:在React引起的事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 state={
    count:0
  }
  handle = () => {
    this.setState({
      count:this.state.count+1
    })
    this.setState({
      count:this.state.count+1
    })
     // 每次只加1
  }
  render() {
    return (
      <div className="App">
        <button onClick={this.handle}>{this.state.count}</button>
      </div>
    );
  }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 state={
    count:0
  }
  handle = () => {
    this.setState((prevState) =>({
       count:prevState.count+1
    }))
    this.setState((prevState) =>({
      count:prevState.count+1
    }))
   // 每次加2
  }
  render() {
    return (
      <div className="App">
        <button onClick={this.handle}>{this.state.count}</button>
      </div>
    );
  }

在生命周期中

1
2
3
4
5
6
7
8
componentDidMount () {
   this.setState({
     count:this.state.count+1
   })
   this.setState({
    count:this.state.count+1
  })
 }
1
2
3
4
5
6
7
8
  componentDidMount () {
    this.setState((prevState) =>({
       count:prevState.count+1
    }))
    this.setState((prevState) =>({
      count:prevState.count+1
    }))
  }

在setTimeout中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
componentDidMount () {
   setTimeout(()=>{
     this.setState({
       count:this.state.count+1
     })
     this.setState({
      count:this.state.count+1
    })
    this.setState({
      count:this.state.count+1
    })
   },1000)
  }
  render() {
    return (
      <div className="App">
        <button >{this.state.count}</button> //3
      </div>
    );
  }

总结: 1.setState为异步:在react的生命周期及由react引起的事件(onClick/onChange)中 2.setState为同步:由原生事件引起的及在setTimeout/setInterval中 3.setState批量操作是否会合并:当setState为异步时且参数为对象,取最后一次来执行,若参数为函数,则每一次都会计算;当setState为同步时,不管参数是对象还是函数,都会执行。

This post is licensed under CC BY 4.0 by the author.