在上一篇中写过,组件能够分为函数式组件和类组件,而且更新组件的方法也给出了经过传入ReactDOM.render()方法进行更新。可是这种方式并不能很好地进行封装成独立功能的组件,一些操做会由外部进行控制。而咱们理想中的组件应该是一个功能独立的个体,只是不一样场合不一样的数据才会出现不一样。
而这就就关联到了咱们此次的主题---状态(State)
状态(state) 和 属性(props) 相似,都是一个组件所须要的一些数据集合,可是它是私有的,而且由组件自己彻底控制,能够认为它是组件的“私有属性(或者是局部属性)”。数组
若是想要使用状态(State)的话,则须要咱们在构建组件的时候是要以类组件为形式的。
针对直接以类组件形式构造的组件不须要变化,那么针对函数式组件该如何转化呢?异步
例如:函数
class Clock extends React.Component { render() { return ( <div> <h1>Hello, world!</h1> <h2>It is {this.props.date.toLocaleTimeString()}.</h2> </div> ); } }
上面示例就是一个简单的类组件Clock。性能
1) 替换 render() 方法中的 this.props.date 为 this.state.date:优化
class Clock extends React.Component { render() { return ( <div> <h1>Hello, world!</h1> <h2>It is {this.state.date.toLocaleTimeString()}.</h2> </div> ); } }
2) 添加一个 类构造函数(class constructor) 初始化 this.state:this
class Clock extends React.Component { constructor(props) { super(props); this.state = {date: new Date()}; } render() { return ( <div> <h1>Hello, world!</h1> <h2>It is {this.state.date.toLocaleTimeString()}.</h2> </div> ); } }
❤ 注意咱们如何将 props 传递给基础构造函数:
constructor(props) { super(props); *** this.state = {date: new Date()}; }
3) 移除 <Clock /> 元素中的 date 属性:code
ReactDOM.render( <Clock />, document.getElementById('root') );
经过上面的步骤就能够实现添加State到类组件了,最终结果:component
class Clock extends React.Component { constructor(props) { super(props); this.state = {date: new Date()}; } render() { return ( <div> <h1>Hello, world!</h1> <h2>It is {this.state.date.toLocaleTimeString()}.</h2> </div> ); } } ReactDOM.render( <Clock />, document.getElementById('root') );
State的初始化和常规的赋值形式是同样的,可是若是咱们须要更新相关数据的话,则须要经过setState方法进行修改,如:对象
this.setState({ date: new Date() });
关于如何正确使用State以及setState() 有三个方面须要注意:继承
正如上面提到的如何修改State那样,在初始化后,若是修改的话只能经过setState方法进行修改。
React 为了优化性能,有可能会将多个 setState() 调用合并为一次更新。
由于 this.props 和 this.state 多是异步更新的,你不能依赖他们的值计算下一个state(状态)。
如:
// 错误 this.setState({ counter: this.state.counter + this.props.increment, });
要弥补这个问题,使用另外一种 setState() 的形式,它接受一个函数而不是一个对象。这个函数将接收前一个状态做为第一个参数,应用更新时的 props 做为第二个参数:
// 正确 this.setState((prevState, props) => ({ counter: prevState.counter + props.increment }));
当你调用 setState(), React 将合并你提供的对象到当前的状态中。因此当State是一个多键值的结构时,能够单独更新其中的一个,此时会进行“差分”更新,不会影响其余的属性值。
生命周期就是指一个对象的生老病死。
而组件的生命周期则是这个组件从建立到销毁的一个过程。在这个过程当中会有不一样的阶段,从而会产生一些对应的生命周期函数来供咱们使用,以便可以进行一些渲染、更新等处理。
能够简单分为几个阶段:
初始化阶段
运行中状态
销毁阶段
不管做为父组件仍是子组件,它都没法获悉一个组件是否有状态,同时也不须要关心另外一个组件是定义为函数组件仍是类组件。
这就是 state(状态) 常常被称为 本地状态 或 封装状态的缘由。 它不能被拥有并设置它的组件 之外的任何组件访问。
一个组件能够选择将 state(状态) 向下传递,做为其子组件的 props(属性):
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
这一般称为一个“从上到下”,或者“单向”的数据流。任何 state(状态) 始终由某个特定组件全部,而且从该 state(状态) 导出的任何数据 或 UI 只能影响树中 “下方” 的组件。
若是把组件树想像为 props(属性) 的瀑布,全部组件的 state(状态) 就如同一个额外的水源汇入主流,且只能随着主流的方向向下流动。
在 React 应用中,一个组件是不是有状态或者无状态的,被认为是组件的一个实现细节,随着时间推移可能发生改变。你能够在有状态的组件中使用无状态组件,反之亦然。