6 State and Lifecycle
状态和生命周期
在第四章节中介绍 更新React element --- 这种方法不可取
function tick() {
const element = (
<div>
<h1>Hello, world!</h1>
<h2>It is {new Date().toLocaleTimeString()}.</h2>
</div>
);
ReactDOM.render(
element,
document.getElementById('root')
);
}
setInterval(tick, 1000);
本章节将介绍更实用的更新 与封装
封装Clock Component
ReactDOM.render(
<Clock />,
document.getElementById('root')
);
State 类似 props ,但是它是私有的完全由组件控制。
1 创建ES6 class 继承React.Component
2 添加render()方法
3 将 element中主体移到render()中
4 通过new Date() 替换成this.props.date 通过props中获取date
5 在<Clock />中添加 date属性
class Clock extends React.Component {
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.props.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
实用状态优化
添加本地状态
1 移除date从props获取 --- 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 添加构造方法 初始化 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>
);
}
}
接下来 设置Clock自动更新显示时间
添加生命周期方法到类中
一个应用中可能有很多组件,组件销毁是释放组件资源很重要
monunt --- 当clock组件第一次渲染DOM 給clock设置计数器被称为 安装
unmount - 当clock组件被DOM中删除 清除clock的计数器 被称为 卸载
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = {date: new Date()};
}
//组件被挂载
componentDidMount() {
}
//组件被卸载
componentWillUnmount() {
}
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
当组件显示在DOM中会执行componentDidMount()回调,可以在这里创建定时器
componentDidMount() {
this.timerID = setInterval(
() => this.tick(),
1000
);
}
当组件从DOM中移除会执行componentWillUnmount()回调,可以在这里清楚定时器
componentWillUnmount() {
clearInterval(this.timerID);
}
最终实现 每秒更新显示时间
1 ReactDOM.render 渲染是加载clock组件
2 首先执行构造方法
3 再执行render
4 当显示在DOM之后执行componentDidMount 设置定时器 1s执行一次tick(),在tickzhong 改变状态 从而页面会执行render
5 当组件销毁 执行componentWillUnmount 清楚 定时器
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = {date: new Date()};
}
componentDidMount() {
this.timerID = setInterval(
() => this.tick(),
1000
);
}
componentWillUnmount() {
clearInterval(this.timerID);
}
tick() {
this.setState({
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')
);
正确使用setState()
1 不要直接修改state ---- 唯一可以直接分配shis.state 是构造方法
// Wrong
this.state.comment = 'Hello';
// Correct
this.setState({comment: 'Hello'});
2 设置state 更新 可能是异步的
React 可能将多个setstate() 在一次更新中处理
想要及时更新 使用
// Correct
this.setState((prevState, props) => ({
counter: prevState.counter + props.increment
}));
// Correct
this.setState(function(prevState, props) {
return {
counter: prevState.counter + props.increment
};
});
6 状态更新合并
constructor(props) {
super(props);
this.state = {
posts: [],
comments: []
};
}
componentDidMount() {
fetchPosts().then(response => {
this.setState({
posts: response.posts
});
});
fetchComments().then(response => {
this.setState({
comments: response.comments
});
});
}
生命周期补充
//1 创建阶段 处理props的默认值
getDefaultProps(){
console.log('getDefaultProps');
}
// 2 作用于组件的实例,在实例创建时调用一次,用于初始化每个实例的state,此时可以访问this.props。
getInitialState(){
console.log('getInitialState');
}
// 3 在完成首次渲染之前调用,此时仍可以修改组件的state。
componentWillMount(){
}
/** 4 render
* 必选的方法,创建虚拟DOM,该方法具有特殊的规则:
只能通过this.props和this.state访问数据
可以返回null、false或任何React组件
只能出现一个顶级组件(不能返回数组)
不能改变组件的状态
不能修改DOM的输出
*/
render() {
return (
<View style={styles.container}>
<Text style={styles.welcome}>
Welcome to React Nativddde!
</Text>
<Text style={styles.instructions}>
To get started, edit index.android.js
</Text>
<Text style={styles.instructions}>
Double tap R on your keyboard to reload,{'\n'}
Shake or press menu button for dev menu
</Text>
</View>
);
}
/**
* 5 componentDidMount
* 真实的DOM被渲染出来后调用,在该方法中可通过this.getDOMNode()访问到真实的DOM元素。
* 此时已可以使用其他类库来操作这个DOM。
*
* 在服务端中,该方法不会被调用。
*
* */
componentDidMount(){
}
/** 6 componentWillReceiveProps
* 组件接收到新的props时调用,
* 并将其作为参数nextProps使用,
* 此时可以更改组件props及state。
* */
componentWillReceiveProps(nextProps){
if (nextProps.bool) {
this.setState({
bool: true
});
}
}
/**
* 7.shouldComponentUpdate
* 组件是否应当渲染新的props或state,返回false表示跳过后续的生命周期方法,通常不需要使用以避免出现bug。在出现应用的瓶颈时,可通过该方法进行适当的优化。
* 在首次渲染期间或者调用了forceUpdate方法后,该方法不会被调用
* */
shouldComponentUpdate(nextProps, nextState){
}
/**
* 8.componentWillUpdate
* 接收到新的props或者state后,进行渲染之前调用,此时不允许更新props或state。
* */
componentWillUpdate(nextProps, nextState){
}
/**
* 9.componentDidUpdate
* 完成渲染新的props或者state后调用,此时可以访问到新的DOM元素。
* */
componentDidUpdate(prevProps, prevState){
}
/**
* 10.componentWillUnmount
* 组件被移除之前被调用,可以用于做一些清理工作,
* 在componentDidMount方法中添加的所有任务都需要在该方法中撤销,
* 比如创建的定时器或添加的事件监听器。
* */
componentWillUnmount(){
}