React this.setState 详解

setState(arg1,arg2) 括号内的arg1可传入两种参数,一种是对象,一种是函数. arg2为更改state之后的回调方法,arg2可为空.

对象式的setState用法

例如:

//第一种
this.setState({ isAuthenticated: true});
this.setState({ isAuthenticated: true},()=>{});

this.setState(
             {isAuthenticated: true},
             () => console.log(this.state.isAuthenticated + '.'));

函数式的setState用法

这个函数会接收到两个参数,第一个是当前的state值,第二个是当前的props,这个函数应该返回一个对象,这个对象代表想要对this.state的更改,换句话说,之前你想给this.setState传递什么对象参数,在这种函数里就返回什么对象,不过,计算这个对象的方法有些改变,不再依赖于this.state,而是依赖于输入参数state。
这个函数格式是固定的,必须第一个参数是state的前一个状态,第二个参数是属性对象props,这两个对象setState会自动传递到函数中去

有两种写法:

//第二种 , 有两种写法 区别在于括号
this.setState((preState, props) => {
                    return {isAuthenticated: props.isAuthen}
                });

this.setState((preState, props) => ({
                    isAuthenticated: !preState.isAuthenticated
                }));

仔细看可以发现,前者是return了一个对象,后者直接写了一个对象,但是后者的对象外层比前者的写法多了个括号,使用时需要注意。
如果你希望在setState之前做些什么 可以使用前者的写法:

 this.setState((preState, props) => {
                    console.log(preState)
                    return {isAuthenticated: true}
                }, () => console.log(this.state.isAuthenticated));
//这个写法意思就是,在改变state中的数据之前,打印出当前的state,然后在更新state之后,
//利用回调打印出this.state.isAuthenticated

使用场景:

调用setState,组件的state并不会立即改变,setState只是把要修改的状态放入一个队列中,React会优化真正的执行时机,并且React会出于性能原因,可能会将多次setState的状态修改合并成一次状态修改。所以不要依赖当前的State,计算下个State。
例如:

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

直观上来看,当上面的incrementMultiple函数被调用时,组件状态的count值被增加了3次,每次增加1,那最后count被增加了3,但是,实际上的结果只给state增加了1。

原因并不复杂,就是因为调用this.setState时,并没有立即更改this.state,所以this.setState只是在反复设置同一个值而已,上面的code等同下面这样。

function incrementMultiple() {
  const currentCount = this.state.count;
  this.setState({count: currentCount + 1});
  this.setState({count: currentCount + 1});
  this.setState({count: currentCount + 1});
}

currentCount就是一个快照结果,重复地给count设置同一个值,不要说重复3次,哪怕重复一万次,得到的结果也只是增加1而已。

那么如果想要结果是3怎么做呢?这时就需要第二种写法:

 _bsetIncrementMultiple = () => {
        this.setState(prevState => ({
            count: prevState.count + 1
        }));
        this.setState(prevState => ({
            count: prevState.count + 1
        }));
        this.setState(prevState => ({
            count: prevState.count + 1
        }));
    }

这样,每一次改变count的时候,都是prevState.count + 1,pervState是前一个状态,每次setState之后,前一个状态都会改变,那么这时候,结果就是想要的3了。如果需要立即setState 那么传入一个函数来执行setState是最好的选择

更详细内容可参考:setState:这个API设计到底怎么样

猜你喜欢

转载自blog.csdn.net/u011272795/article/details/80882567