Hooks 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。
Hooks 是一种在函数式组件中使用有状态函数的方法。
Hooks不支持在class中使用,比如在class中使用useState和useEffect都是不允许的。
在使用Hooks之前我们必须要要做明白一下几点:
Hooks最为常见的有两个API:useState
与useEffect
也叫State Hook
与Effect Hook
,那么接下来我们就来学习下在React Native中如何使用这两个API。
首先需要指出的是Hooks 是 React 16.8 的新增特性,因此我们不需要引入其它任何库,只需要确保项目依赖的React大于等于16.8即可。
需求1:假如我们有个需求将从网络上请求到的数据显示在界面上,我们先看它的class写法:
import React from 'react';
import {
SafeAreaView,
Text,
TouchableOpacity
} from 'react-native';
import Constants from './expand/dao/Constants';
import { post } from './expand/dao/HiNet';
class HiNetDemo extends React.Component<{}, { msg: string }> {
constructor(props: any) {
super(props);
this.state = {
msg: ''
}
}
doFetch = () => {
const formData = new FormData();
formData.append("requestPrams", 'RN');
post(Constants.test.api)(formData)().then(result => {
this.setState({
msg: JSON.stringify(result)
});
}).catch(e => {
console.log(e);
this.setState({
msg: JSON.stringify(e)
});
})
}
render() {
return (
<SafeAreaView>
<TouchableOpacity onPress={this.doFetch}>
<Text>加载</Text>
</TouchableOpacity>
<Text>{this.state.msg}</Text>
</SafeAreaView>
);
}
}
那么它对应的hooks写法该是怎样子的呢?
下面代码接借助RReact Native的HiNet网络框架发出网络请求并通过useState
来控制msg
的状态,并将其展示在界面上:
import React, { useState } from 'react';
import {
SafeAreaView,
Text,
TouchableOpacity
} from 'react-native';
import Constants from './expand/dao/Constants';
import { post } from './expand/dao/HiNet';
export default (props: any) => {
const [msg, setMsg] = useState('');
const doFetch = () => {
const formData = new FormData();
formData.append("requestPrams", 'RN');
post(Constants.test.api)(formData)().then(result => {
setMsg(JSON.stringify(result));
}).catch(e => {
console.log(e);
setMsg(JSON.stringify(e));
})
}
return (
<SafeAreaView>
<TouchableOpacity onPress={doFetch}>
<Text>加载</Text>
</TouchableOpacity>
<Text>{msg}</Text>
</SafeAreaView>
);
};
从上述代码中我们不难看出,在React Native中使用State Hook
的主要步骤:
useState
:import React, { useState } from 'react';
useState
定义state:const [msg, setMsg] = useState('');
set+变量名首字母大写
setMsg
修改即可setMsg(JSON.stringify(result));
State Hook
的作用范围:因为Hooks只能应用与函数式组件,所以通过它声明的state的作用范围是函数内;上面代码是摘自《网络编程与数据存储技术》一章。
Effect Hook 可以让你在函数组件中执行副作用操作。
我们可以把 useEffect Hook 看做React class 的生命周期函数:componentDidMount
、componentDidUpdate
和 componentWillUnmount
这三个函数的组合。
需求2:假如我们需要在页面完成装载后的某个时刻执行某个操作,在页面卸载时执行一些清理会资源回收操作。
对于这样的一个需求对应的class代码如下:
import React from 'react';
import {
SafeAreaView,
StyleSheet,
Text,
TouchableOpacity
} from 'react-native';
import Constants from './expand/dao/Constants';
import { post } from './expand/dao/HiNet';
export default class HiNetDemo extends React.Component<{}, { msg: string }> {
timer: any;
constructor(props: any) {
super(props);
this.state = {
msg: ''
}
}
componentDidMount() {
this.timer = setTimeout(() => {
this.doFetch();
}, 2000);
}
componentWillUnmount() {
this.timer && clearTimeout(this.timer);
}
doFetch = () => {
const formData = new FormData();
formData.append("requestPrams", 'RN');
post(Constants.test.api)(formData)().then(result => {
this.setState({
msg: JSON.stringify(result)
});
}).catch(e => {
console.log(e);
this.setState({
msg: JSON.stringify(e)
});
})
}
render() {
return (
<SafeAreaView>
<TouchableOpacity onPress={this.doFetch}>
<Text>加载</Text>
</TouchableOpacity>
<Text>{this.state.msg}</Text>
</SafeAreaView>
);
}
}
componentDidMount
通过定时器实现了当页面完成装载后2s发起了网络请求;那么,上述功能用Effect Hook又该如何实现呢?
还是以《网络编程与数据存储技术》一章的网络编程一节为原型我们用Hooks来实现上述需求:
import React, { useState, useEffect } from 'react';
import {
SafeAreaView,
StyleSheet,
Text,
TouchableOpacity
} from 'react-native';
import Constants from './expand/dao/Constants';
import { post } from './expand/dao/HiNet';
export default (props: { navigation: any }) => {
const [msg, setMsg] = useState('');
useEffect(() => {
//对应componentDidUpdate
function handleStatusChange(status: any) {
console.log(status);
}
const timer = setTimeout(() => {
doFetch();
}, 2000);
// 对应componentWillUnmount
return function cleanup() {
timer && clearTimeout(timer);
};
});
const doFetch = () => {
const formData = new FormData();
formData.append("requestPrams", 'RN');
post(Constants.test.api)(formData)().then(result => {
setMsg(JSON.stringify(result));
}).catch(e => {
console.log(e);
setMsg(JSON.stringify(e));
})
}
return (
<SafeAreaView>
<TouchableOpacity onPress={doFetch}>
<Text>加载</Text>
</TouchableOpacity>
<Text>{msg}</Text>
</SafeAreaView>
);
};
在上述代码中我们借助useEffect
实现了class相同的功能,接下来我们来总结下在RN中使用Effect Hook的关键点:
useEffect
:import React, { useState,useEffect } from 'react';
useEffect
来实现不同生命周期函数的hooks:
useEffect(() => {}
一层的会在组件装载时调用,对应componentDidMounthandleStatusChange
对应componentDidUpdate
cleanup
对应componentWillUnmount
在组件卸载时调用最后跟小伙伴们聊一聊什么时候该用Hooks?什么时候该用class?