第七节:组件的state状态

85 阅读4分钟

组件的state状态

初识state

state的作用

对React来说,处理接收外部props,内部也有不同的状态。

state状态的作用是管理当前组件的内部数据,让React组件可以随用户操作、网络响应或者其他变化而动态更改输出内容

为class组件添加state

React规定:组件的内部状态记录在组件的this.state对象上面

  • 方法一:为组件添加constructor构造函数,然后在该函数中为this.state赋初始值
class App extends React.Component { 
constructor(){ 
super(); 
this.state = { count: 0}    
}    
render(){ 
return <button>你点了我 {this.state.count} 次</button>    
} }
  • 方法二:使用class属性新提案
class App extends React.Component {
state = { count: 0 }
render(){
return <button>你点了我 {this.state.count} 次</button>     
} }

将props的数据挂载到state

之前说过,React组件是不能修改props属性的,但是可以把props挂载到state对象上,将其视为组件所需管理的数据之一,如:

class Counter extends React.Component {
constructor(props){ 
super(props);         
this.state = {
// 若 props 未传入 count,则赋初始值为 0             
count: this.props.count || 0        
}     
}    
render(){ 
return <button>你点了我 {this.state.count} 次</button>    
} }

若需要在constructor函数函数中访问this.props,则使用props参数来调用父类的构造函数是必须的,否则会出现this.props为undefined的Bug

更新state、更新组件

setState API

更新组件state的唯一方式是调用组件实例的setState()方法。

setState(Object || Function [, callback])

API解析:

  • 作用:将第一个参数返回的对象与组件当前的状态对象(this.state)进行浅层合并,并通知React使用更新后的state重新渲染此组件.

  • 参数:

    1、第一个参数可以说Function类型或Object类型。

     // Function 类型可接收两个形参:state 与 props,分别表示组件当前的 state 与    props 
     setState((state, props) => {})
    

    2、callback为可选的回调函数,它将在state完成对象合并、并重新渲染组件后执行

组件更新

使用setState()更新组件视图:

class Counter extends React.Component {
constructor(props){
super(props); 
this.state = { 
count: this.props.count || 0 
}     
}     
handleClick = () => {
let {count} = this.state;
this.setState({count: ++count}) 
}   
render(){ 
return 
<button onClick={this.handleClick}>你点了我 {this.state.count} 次</button>    
} }

执行流程:

  1. 触发handleClick函数,计算count值并调用setState方法
  2. {count:++count}的返回值与组件当前的状态对象(this.state)进行浅合并
  3. 触发组件的render函数,对比状态更新前后的虚拟DOM,在需要更新的地方更新视图

state的私有性

state状态即组件数据,它是私有的,完全由当前组件来控制 比如复用上面的Counter组件:

class App extends React.Component {
render() {  
return ( 
<div>   
<Counter /> 
<Counter count={0} />                
<Counter count={17} />  
</div>        
)    
} }

当点击按钮后,每个组件都各自维护自己的state,每个按钮的点击次数不会彼此受到影响。

state的三个注意点

不要直接修改state

React规定:class组件的constructor构造函数是唯一可以给this.state赋值的地方

应该是使用setState进行赋值

state的更新会被合并

当你调用setState的时候,React会把你提供的对象合并到当前的state,意味者你可以单独更新state的某个变量。 例子:

constructor(props) { 
super(props); 
this.state = { 
posts: [],  
comments: []  
}; }

然后分别调用setState来单独地更新它们

queryData() {
fetchPosts().then(response => { 
this.setState({ 
posts: response.posts 
});
});   
fetchComments().then(response => { 
this.setState({ 
comments: response.comments 
});    
});
}

state的更新是异步的

React出于性能考虑,会把多个setState()调用合并成一个调用,这意味着调用setState()this.statethis.props并不会被立即更新.

例如:

handleClick = () => {
let { count } = this.state;
this.setState({ count: count }) 
}

由于更新是异步的,无法保证每次事件触发都能获取更新后的值,有可能会返回旧的state。 为了解决这个问题,可以让setState接收一个函数而不是一个对象,这个函数可以用上一个state作为第一个参数,将此次更新被应用时的props作为第二个参数

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

props与state的对比

相同:

  1. 都是普通的js对象
  2. 都是用来保存组件信息的
  3. props与state所保存的信息都可控制组件的渲染输出

不同点:

  1. props是外部传递给组件的
  2. state是组件内部由组件自己管理的,类似于在一个函数内声明的变量

有状态组件与无状态组件

有状态组件:

function Welcome (props) { return <h1>{ props.name }~ 你好呀!</h1> }

有状态组件:

class Welcome extends React.Component {
state = { name : "Alan" }  
render(){    
return <div>Hello,{this.state.name}</div>  
} }

注:16.8版本之后,提出了新的Hook,可以在不编写class的情况下使用state以及他的React特性