用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
posted @ 2021-02-15 10:11  BAEBAE996  阅读(2256)  评论(0编辑  收藏  举报