React中State状态

2019-04-021651次阅读React

React的核心思想是组件化,而组件中最重要的概念是State(状态),State是一个组件的UI数据模型,是组件渲染时的数据依据。默认情况下,此State状态不会与组件的父组件或子组件共享。它完全由组件本身拥有和控制。下面是一个具有State状态的简单组件。

class Component extends React.Component {
    constructor(props){
        super(props);
        this.state = {
            counter: 0 
        }
    }

    render() {
        return <div>{this.state.counter}</div>
    }
}

如何更新State状态

React提供了一个名为setState的函数。您应该始终使用setstate函数来更改状态,而不要直接改变它

//千万不要这样做
this.state.counter = 2;

//总是这样做
this.setState({
    counter: 2
});

setState

setState函数的第一个参数可以采用新的状态对象或函数。它还有一个可选的第二个参数,这是一个在状态更新时执行的回调。

setState(newState || function, optional callback)

setState更新状态的方式是:

如果setstate函数的第一个参数是一个对象,它将当前状态对象与传递给setstate函数的任何对象合并。例如:

state = { a: 1, b: 2, c: 3} //当前状态
this.setState({ a: 3 }); //参数是一个对象

//它将**合并**初始状态与传递给setState的对象
//结果只更新该键的值
state = { a: 3, b: 2, c: 3 } //SetState刷新后的状态

如果第一个参数是一个函数,那么它首先通过将当前状态作为参数传递来执行该函数。函数必须返回一个对象。然后它将这个输出与当前状态合并,就像上面所做的那样。例如:

state = { a: 1, b: 2, c: 3} //初始状态
//我们用函数调用了setstate
this.setState(currentState => ({
    a: currentState.a + 1
}));
//通过将当前状态对象作为参数传递来执行函数。
//由于currentState.a为1,函数返回a:2
//现在它将返回的对象与原始状态合并
state = { a: 2, b: 2, c: 3 } //调用setState后的状态

关于setState函数,您必须知道的一件事是它可能是异步的。所以不要依赖它来立即更新状态。这不是一个bug,它是按设计的。如果您想了解setstate调用背后的异步设计决策,这里有一个很好的解释

由于setState可以是异步的,所以下面的代码不会给您正确的结果,因为到了console.log state.counter值时,它将不会被更新。

//错误的结果。不要依靠setstate来同步
console.log(this.state.counter);//打印 0
this.setState({
    counter: this.state.counter + 1
}); //这是异步调用
console.log(this.state.counter);//静态打印 0

另外,如果要使用当前状态值更新状态,请始终在setstate内使用updater函数,而不是传递对象。例如,下面的代码将不起作用。

//总是这样做
//如果使用当前状态值更新状态,请始终使用updater函数
console.log(this.state.counter); //prints 0
this.setState((state) => ({ counter: state.counter + 1}) );
this.setState((state) => ({ counter: state.counter + 1}) );
this.setState((state) => ({ counter: state.counter + 1}) );
//这是保证工作的!
//当所有三个调用都刷新时,
//this.state.counter将为3

State注意事项:

  • 不要直接改变State状态。始终使用this.setState更新状态。
  • 如果新State状态不依赖于旧State状态,则可以使用this.setState(object)构建。
  • 如果新状态依赖于旧状态,则使用this.setState(function(currentState){ .. })构建。

Props属性与State状态有什么不同,又有什么相似之处?

  • State状态和props之间的区别在于,State状态是私有的,并且完全受控于当前组件,而props是由组件的父组件传递给子组件的东西。
  • 相似性(有点类似)是,当组件的State状态更改或组件的props属性更改时,响应地会自动重新render组件。
  • 组件的render函数是一个同时具有状态和属性的函数,这意味着它定义了给定状态和属性时组件的外观。
  • 它应该是纯粹的函数,从某种意义上说,如果组件具有相同的状态和属性,那么无论调用多少次,它都应该呈现完全相同的内容,并且不应该有任何副作用。

延伸:

啥时候用到State

  • 组件中用到的一个变量是不是应该作为组件State,可以通过下面的4条依据进行判断:
  • 这个变量是否是通过Props从父组件中获取?如果是,那么它不是一个state状态。
  • 这个变量是否在组件的整个生命周期中都保持不变?如果是,那么它不是一个state状态。
  • 这个变量是否可以通过其他状态(State)或者属性(Props)计算得到?如果是,那么它不是一个state状态。
  • 这个变量是否在组件的render方法中使用?如果不是,那么它不是一个state状态。这种情况下,这个变量更适合定义为组件的一个普通属性,例如组件中用到的定时器,就应该直接定义为this.timer,而不是this.state.timer。
  • 并不是组件中用到的所有变量都是组件的state状态!当存在多个组件共同依赖一个state状态时,一般的做法是state状态上移,将这个state状态放到这几个组件的公共父组件中。

为啥说setState函数有可能是异步的

要知道setState本质是通过一个队列机制实现state更新的。 执行setState时,会将需要更新的state合并后放入状态队列,而不会立刻更新state,队列机制可以批量更新state。

如果不通过setState而直接修改this.state,那么这个state不会放入状态队列中,下次调用setState时对状态队列进行合并时,会忽略之前直接被修改的state,这样我们就无法合并了,而且实际也没有把你想要的state更新上去。
 

上一篇: React中Props属性  下一篇: 搬瓦工(Bandwagon)商家 VPS主机套餐信息  

React中State状态相关文章