在上文《React1 创建React组件、组件的属性》 中,了解到组件的视图是属性的映射,通过改变组件属性可以触发组件重新渲染,从而改变组件的视图
其实组件的视图是由属性和内部状态映射而来的,即 view=f(props,state),跟属性类似,状态的改变也会触发组件的重新渲染,只不过状态是组件内部基于自身逻辑或者用户事件自己维护的,而不是由外部输入。
组件的内部状态
可以通过 ReactDOM.render(
示例:
function Clock(props){
return (
Hello World
It Is {props.time}
)
}
function tick(){
ReactDOM.render(
,
document.getElementById('root')
)
}
setInterval(tick,1000)
示例解析:
例子中定义了一个 Clock 组件,组件接收一个 time 属性,在组件外部通过 setInterval 周期性的调用 ReactDOM.render 不断更新 Clock 的属性并重新渲染
在实际场景中,对于一个时钟组件,我们希望只调用一次 ReactDOM.render(
更容易在页面上放置多个时钟,即复用性更好。
要达到这个目的,就需要组件内部状态来支持。组件有一个特殊的属性 state 用来保存组件的内部状态。
用户可以通过 this.setState(statePatch) 来更新组件的状态,组件的状态更新后会重新执行 render 方法来更新视图,以上例子内部改造后
示例:
class Clock extends React.Component{
construstor(props){
super(props);
this.state={
time:new Date();
}
}
componentDidMount(){
this.timeID=setInterval(()=>this.tick(),1000);
}
componentWillUnmount(){
clearInterval(this.timeID)
}
tick(){
this.setState({
time:new Date()
})
}
render(){
return(
Hello World
It Is {this.state.time.toLocaleTimeString()}
)
}
}
ReactDOM.render(
,
document.getElementById('root')
)
此时,Clock 作为一个完整的时钟组件就可以自己更新自己了,如果想要使用组件的内部状态,那组件必须以类继承的方式来定义,而不能使用函数式组件
所以说,函数式组件也被常称作为无状态组件(stateless)
例子中有用到 componentDidMount 和 componentWillUnmount 两个函数,它们是组件的生命周期函数
改造后的例子,只需要调用一次 ReactDOM.render 即可,在实例的项目中,一个完整的单页面web应用,
也只需要调用一次 ReactDOM.render 方法把根组件挂载到页面中即可
初始化组件内部状态
在创建一个拥有内部状态的组件时,需要对内部状态进行初始化,即设置组件的最初状态是什么,
是在构造函数 constructor 中设置 state 属性就可以
示例:
class MyComponent extends React.Component{
construstor(props){
super(props); //这行代码不可缺少
this.state={
name:'Luky'
}
}
}
setState 大多数情况下是异步的
setState 多数情况下是异步的,异步意味着通过 setState 更新组件状态后, 不能立刻通过 this.state 来获取到更新后的值
另外当连续多次调用 setState 来更新同一个字段时,只有最后一次更新才会生效
示例:
class Test extends React.Component{ constructor(props){ super(props); this.state={ value:0 } } addTree(){
this.setState({value:this.state.value+1}); this.setState({value:this.state.value+2}); this.setState({value:this.state.value+3});
} render(){ return (
) } } ReactDOM.render(Value:{this.state.value}
, document.getElementById('root') )
如果需要代码正常工作,需要通过回调函数的方式来生成下一个state
示例:
this.setState(preState=>({value:preState.value+1}));
this.setState(preState=>({value:preState.value+2}));
this.setState(preState=>({value:preState.value+3}));
示例结果:
解析:
实际上只有在React能控制的事件处理过程中调用的 setState 才是异步的,如:生命周期函数,React内置的button、input等组件的事件处理函数
在某些特殊的组件中,可能需要通过addEventListener来设置某些DOM事件处理函数,在这种通过原生JS API 来设置的事件处理过程中调用setState就是同步的,
会立即更新 this.state,另外还有 setInterval、setTimeout等原生API的回调函数也是如此
文件借鉴于: http://react-china.org/t/react-react/15548