【React系列】状态(State)和生命周期
在上一篇中写过,组件可以分为函数式组件和类组件,并且更新组件的方法也给出了通过传入ReactDOM.render()方法进行更新。但是这种方式并不能很好地进行封装成独立功能的组件,一些操作会由外部进行控制。而我们理想中的组件应该是一个功能独立的个体,只是不同场合不同的数据才会出现不同。
而这就就关联到了我们这次的主题---状态(State)
状态(State)
什么是状态
状态(state) 和 属性(props) 类似,都是一个组件所需要的一些数据集合,但是它是私有的,并且由组件本身完全控制,可以认为它是组件的“私有属性(或者是局部属性)”。
函数式组件转化为类组件
如果想要使用状态(State)的话,则需要我们在构建组件的时候是要以类组件为形式的。
针对直接以类组件形式构造的组件不需要变化,那么针对函数式组件该如何转化呢?
- 创建一个继承自 React.Component 类的 ES6 class 同名类。
- 添加一个名为 render() 的空方法。
- 把原函数中的所有内容移至 render() 中。
- 在 render() 方法中使用 this.props 替代 props。
- 删除保留的空函数声明。
例如:
class Clock extends React.Component {render() {return (<div><h1>Hello, world!</h1><h2>It is {this.props.date.toLocaleTimeString()}.</h2></div>);}
}
上面示例就是一个简单的类组件Clock。
类组件中添加State
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:
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 属性:
ReactDOM.render(<Clock />,document.getElementById('root')
);
通过上面的步骤就可以实现添加State到类组件了,最终结果:
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
State的初始化和常规的赋值形式是一样的,但是如果我们需要更新相关数据的话,则需要通过setState方法进行修改,如:
this.setState({date: new Date()
});
正确地使用 State(状态)
关于如何正确使用State以及setState() 有三个方面需要注意:
不要直接修改 state(状态)
正如上面提到的如何修改State那样,在初始化后,如果修改的话只能通过setState方法进行修改。
state(状态) 更新可能是异步的
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
}));
state(状态)更新会被合并
当你调用 setState(), React 将合并你提供的对象到当前的状态中。所以当State是一个多键值的结构时,可以单独更新其中的一个,此时会进行“差分”更新,不会影响其他的属性值。
生命周期方法
什么是生命周期
生命周期就是指一个对象的生老病死。
而组件的生命周期则是这个组件从创建到销毁的一个过程。在这个过程中会有不同的阶段,从而会产生一些对应的生命周期函数来供我们使用,以便能够进行一些渲染、更新等处理。
可以简单分为几个阶段:
初始化阶段
- getDefaultProps:获取实例的默认属性(即使没有生成实例,组件的第一个实例被初始化CreateClass的时候调用,只调用一次,)
- getInitialState:获取每个实例的初始化状态(每个实例自己维护)
- componentWillMount:组件即将被装载、渲染到页面上(render之前最好一次修改状态的机会)
- render:组件在这里生成虚拟的DOM节点(只能访问this.props和this.state;只有一个顶层组件,也就是说render返回值值职能是一个组件;不允许修改状态和DOM输出)
- componentDidMount:组件真正在被装载之后,可以修改DOM
运行中状态
- componentWillReceiveProps:组件将要接收到属性的时候调用(赶在父组件修改真正发生之前,可以修改属性和状态)
- shouldComponentUpdate:组件接受到新属性或者新状态的时候(可以返回false,接收数据后不更新,阻止render调用,后面的函数不会被继续执行了)
- componentWillUpdate:不能修改属性和状态
- componentDidUpdate:可以修改DOM
销毁阶段
- componentWillUnmount:开发者需要来销毁(组件真正删除之前调用,比如计时器和事件监听器)
数据向下流动
无论作为父组件还是子组件,它都无法获悉一个组件是否有状态,同时也不需要关心另一个组件是定义为函数组件还是类组件。
这就是 state(状态) 经常被称为 本地状态 或 封装状态的原因。 它不能被拥有并设置它的组件 以外的任何组件访问。
一个组件可以选择将 state(状态) 向下传递,作为其子组件的 props(属性):
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
这通常称为一个“从上到下”,或者“单向”的数据流。任何 state(状态) 始终由某个特定组件所有,并且从该 state(状态) 导出的任何数据 或 UI 只能影响树中 “下方” 的组件。
如果把组件树想像为 props(属性) 的瀑布,所有组件的 state(状态) 就如同一个额外的水源汇入主流,且只能随着主流的方向向下流动。
结语
在 React 应用中,一个组件是否是有状态或者无状态的,被认为是组件的一个实现细节,随着时间推移可能发生改变。你可以在有状态的组件中使用无状态组件,反之亦然。
【React系列】状态(State)和生命周期相关推荐
- React文档(六)state和生命周期
想一下之前的章节时钟的例子. 目前为止我们只学习了一直方式去更新UI. 我们调用ReactDOM.render()方法去改变渲染的输出: function tick() {const element ...
- Android之React Native 中组件的生命周期
React Native 中组件的生命周期 概述 就像 Android 开发中的 View 一样,React Native(RN) 中的组件也有生命周期(Lifecycle).所谓生命周期,就是一个对 ...
- Flutter State 的生命周期
本文主要介绍类比 Android 和 iOS,了解 Flutter State 的生命周期. 从 Android 或 iOS 转到 Flutter 开发,最让人疑惑的是 Flutter 如何处理生命周 ...
- 【Java进阶营】Java技术专题「难点-核心-遗漏」Java线程状态流转及生命周期的技术指南(知识点串烧)
前提介绍 本章主要介绍相关线程声明周期的转换机制以及声明周期的流转关系以及相关AQS的实现和相关的基本原理,配合这相关官方文档的中英文互译的介绍. 线程状态流转及生命周期 当线程被创建并启动以后,它既 ...
- 【深入浅出Java并发编程指南】「难点 - 核心 - 遗漏」线程状态流转及生命周期的技术指南(知识点串烧)
前提介绍 本章主要介绍相关线程声明周期的转换机制以及声明周期的流转关系以及相关AQS的实现和相关的基本原理,配合这相关官方文档的中英文互译的介绍. 线程状态流转及生命周期 当线程被创建并启动以后,它既 ...
- [react] React16废弃了哪些生命周期?为什么?
[react] React16废弃了哪些生命周期?为什么? React16废弃的生命周期有3个will: componentWillMount componentWillReceiveProps co ...
- [react] 函数式组件有没有生命周期?为什么?
[react] 函数式组件有没有生命周期?为什么? 没有生命周期 因为他没有继承React.Component 所以也不需要render() 个人简介 我是歌谣,欢迎和大家一起交流前后端知识.放弃很容 ...
- React State和生命周期 3
微信小程序开发交流qq群 173683895 承接微信小程序开发.扫码加微信. 一:组件的生命周期 组件的生命周期可分成三个状态: 安装:已插入真实DOM 更新:正在被重新渲染 卸载:已移出 ...
- React 第五章 state 组件生命周期
本章我们主要讲解 组件之state使用,以及组建的生命周期,在本章我们将使用class进行组件编写. 1,组件的状态state 在之前我们讲过一个页面时间的例子,之前我们使用的属性props进行定时页 ...
- React Native之组件(Component)生命周期学习笔记
1.Component介绍 一般Component需要被其它类进行继承,Component和Android一样,也有生命周期 英文图片如下 2 具体说明 1).挂载阶段 constructor() ...
最新文章
- 借鉴丰田方法对大型软件组织进行敏捷改造 (上)
- Fibonacci数列时间复杂度之美妙
- nginx的模块开发
- php求数组交集的自定义函数,php数组交集函数
- 如何进入embl的ebi网站fasta3服务器,The EMBL-EBI bioinformatics web and programmatic tools framework...
- Arthas - Java 线上问题定位处理的终极利器
- 各种文件系统支持的最大硬盘容量
- 618 技术特辑(一)不知不觉超预算3倍,你为何买买买停不下来?
- 点击键盘上的“Next”button实现文本框焦点跳转
- python中3个线程并发实现_Python3线程中的异步并发是什么?
- NYOJ.904 search(二分查找,快速排序,结构体运用)
- dubbo源码解析-服务暴露原理
- 开源项目工时系统_GitHub - fjp203/timemaker: 定额工时管理系统
- 三星堆的青铜机器人_三星堆“青铜大立人”,手里原来握的是什么东西,至今困扰考古界...
- 计算机用户文件夹加密,windows7电脑文件夹怎么加密
- android实现拍照及获取照片上传至接口
- Python常用STL
- Zeev Suraski、Andi Gutmans、Rasmus Lerdorf
- win7系统安装telnet服务器,Win7系统下怎么安装Telnet服务【图文教程】
- 七.全文检索ElasticSearch经典入门-聚合查询