React setState需要注意的地方

  1. React setState需要注意的地方

React setState需要注意的地方

函数内部多次调用setState,会将所有的setState操作进行合并,如果有修改到相同的属性,谁在最后执行谁,例如下面调用3次setStatecount初始值是0,依次修改count的值,分别加1,加2,加3,最终count的值会被修改为3,而不是6

import React from 'react'

class Counter extends React.Component {
    constructor(props) {
        super(props)
        this.state = {
            count: 0,
        }
    }

    clickHandle = () => {
        this.setState({
            count: this.state.count + 1
        })
        this.setState({
            count: this.state.count + 2
        })
        this.setState({
            count: this.state.count + 3
        })
    }

    render () {
        console.log('render');
        return (
            <div>
                <h1 id="title">计数器:{this.state.count}</h1>
                <button onClick={this.clickHandle}>+1</button>
            </div>
        )
    }
}

export default Counter

如果我们想要结果为6,就是都执行的话,需要给setState传入一个函数,函数的入参分别是最新的state和最新的props,可以进行解构,得到自己想要的值,下面的setState执行了3次,每次都拿到了最新的state,因此count最终会被修改为6

// ...
clickHandle = () => {
    this.setState((state, props) => {
        console.log(state);          // {count: 0}
        return {
            count: state.count + 1
        }
    })
    this.setState((state, props) => {
        console.log(state);          // {count: 1}
        return {
            count: state.count + 2
        }
    })
    this.setState(({count}, props) => {
        console.log(count);          // 3
        return {
            count: state.count + 2
        }
    })
}

我们设置了setState,怎么拿到最新的值呢?直接在setState后面获取行不行?答案是不行,因为setState异步的,因此每次拿到的都是初始值,也就是0

// ...
clickHandle = () => {
    this.setState((state, props) => {
        console.log(state);          // {count: 0}
        return {
            count: state.count + 1
        }
    })

    // 这里获取到的值是0,因为setState是异步的
    console.log(this.state.count) // 0
}

那有什么方法可以拿到修改后的值呢?我们可以给setState传入第二个参数,是一个函数,可以拿到setState修改后的值,但是请注意,是所有setState合并执行后的值

// ...
clickHandle = () => {
    this.setState((state, props) => {
        return {
            count: state.count + 1
        }
    }, () => {
        console.log('更新后的状态:', this.state.count);  // 2
    })

    this.setState((state, props) => {
        return {
            count: state.count + 1
        }
    }, () => {
        console.log('更新后的状态:', this.state.count);  // 2
    })
}

除了上面的方式使得我们可以同步设置state,还有其他一些方法,但是我们只推荐使用上面的方法,下面的方法都不建议使用

  • 定时器

    // ...
      clickHandle = () => {
      setTimeout(() => {
        this.setState({ count: this.state.count + 1 })
        console.log(this.state.count);  // 这里获取到的就是修改后的count 1
      }, 0)
      setTimeout(() => {
        this.setState({ count: this.state.count + 1 })
        console.log(this.state.count);  // 这里获取到的就是修改后的count 2
      }, 0)
    }
    
  • 原生事件中修改状态

    // ...
    clickHandle = () => {
      this.setState({ count: this.state.count + 1 })
      console.log(this.state.count);    // 这里获取到的就是修改后的count 1
      this.setState({ count: this.state.count + 1 })
      console.log(this.state.count);    // 这里获取到的就是修改后的count 2
    }
      componentDidMount() {
      this.btnRef.addEventListener('click', this.clickHandle, false)
    }
    
  • 使用async/await (不规范,不建议使用)

    clickHandle = async () => {
      await this.setState({ count: this.state.count + 1 })
      console.log(this.state.count);  // 这里获取到的就是修改后的count 1
      await this.setState({ count: this.state.count + 1 })
      console.log(this.state.count);  // 这里获取到的就是修改后的count 2
    }
    

转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 289211569@qq.com