用React hooks写一个简单的倒计时页面
useState的基本用法
useState用于向函数组件添加状态
它接收一个参数作为状态的初始值,并返回一个数组
数组的第一个值为状态,第二个值为改变状态的函数
import React, { useState } from 'react'
function stateClass(){
const [name, setName] = useState('hong')
return (
<div>
<div>hello,{name}</div>
<button onClick={() => {setName('nihao')}}>点击</button>
</div>
)
}
export default stateClass
在组件中读状态:直接访问状态名即可
在组件中修改状态:调用函数,传入状态改变后的值
useEffect的基本用法
useEffect的作用是:添加组件已挂载的信号,并执行(和清理)副作用
它可以接收2个参数:回调函数、数组
1、只接收第一个参数:
当componentDidMount的时候,执行回调函数
当useState声明的状态被更新(视图重新渲染)后,也执行回调函数
2、接收2个参数:“effect依赖于某一些state”
数组中写的是用useState定义的状态名称
只有当数组中的状态发生更新时,才执行回调函数
如果我们希望回调函数只在componentDidMount的时候执行一次,就可以写一个空的数组(称为“跳过effect")
3、回调函数的返回值
useEffect的回调函数允许返回一个函数,用来清理副作用
默认情况下(useEffect不写第二个参数),只会在组件卸载(componentWillUnmount)的时候执行这个返回的函数
如果useEffect多次执行,在调用一个新的effect之前会对前一个effect进行清理
例子:我们想要订阅this.props.friend.id的变化:
useEffect(() => {
// ...
ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
return () => {
ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
};
可能产生的动作序列如下:
// Mount with { friend: { id: 100 } } props
ChatAPI.subscribeToFriendStatus(100, handleStatusChange); // 运行第一个 effect
// Update with { friend: { id: 200 } } props
ChatAPI.unsubscribeFromFriendStatus(100, handleStatusChange); // 清除上一个 effect
ChatAPI.subscribeToFriendStatus(200, handleStatusChange); // 运行下一个 effect
// Update with { friend: { id: 300 } } props
ChatAPI.unsubscribeFromFriendStatus(200, handleStatusChange); // 清除上一个 effect
ChatAPI.subscribeToFriendStatus(300, handleStatusChange); // 运行下一个 effect
// Unmount
ChatAPI.unsubscribeFromFriendStatus(300, handleStatusChange); // 清除最后一个 effect
需求分析
- 动态地、实时地显示倒计时的时间
- 倒计时结束后,自动跳转到另外一个页面
代码实现
首先我们需要一个counter状态,表示 正在倒数的时间
还有一个timerID状态,用来保存计时器的ID
其次,当页面挂载完成的时候,需要创建一个计时器,待1s后执行count-1的操作
然后清理上一个计时器,并再次创建计时器,1s后执行count-1的操作...
我们可以利用useEffect的特性来实现这个功能:
const [timerID, setTimerID] = useState(null);
const [counter, setCounter] = useState(5);
useEffect(() => {
if(counter > 0){
let timer = setTimeout(() => {
setCounter(counter-1)
}, 1000);
setTimerID(timer)
}else{
props.history.push('/order')
}
return () => {
setTimerID(null)
}
},[counter]);
页面挂载完成时:counter = 5,执行回调函数,保存计时器ID
1s后,执行计时器,count = 4
useEffect发现count更新,先清理副作用(setTimerID(null)),再新建计时器
1s后,执行计时器,count = 3
...如此循环直到count = 0 时,利用react-router做页面的跳转
完整代码如下:
import React, {useState,useEffect} from 'react'
function Reminder(props) {
const [timerID, setTimerID] = useState(null);
const [counter, setCounter] = useState(5);
useEffect(() => {
if(counter > 0){
let timer = setTimeout(() => {
setCounter(counter-1)
}, 1000);
setTimerID(timer)
}else{
props.history.push('/order')
}
return () => {
setTimerID(null)
}
},[counter]);
return (
<div>
<p>{counter}秒后将自动跳转至订单页面...</p>
</div>
);
}
export default Reminder