React Native 中实现倒计时功能

 

正文

在 React Native,该如何实现一个倒计时功能呢?

 

首次实现

表面看来很简单,譬如像下面这样:

const timer = useRef<ReturnType<typeof setInterval> | null>(null)
const [count, setCount] = useState(0)
const start = () => {
setCount(10)
timer.current = setInterval(() => {
  setCount((count) => count - 1)
}, 1000)
}
useEffect(() => {
if (count === 0 && timer.current !== null) {
  clearInterval(timer.current)
  timer.current = null
}
}, [count])

这段代码大多数情况下是可以正常工作的。但是你将应用退到后台,稍后再进入看看。

很有可能,原本应该结束的倒计时,还在工作。

这是因为 React Native 应用退到后台后,世界会停止。为了适应这点,我们应该先设定希望倒计时结束的时间,然后每隔一秒计算一次当前时间与结束时间之差(秒)。

此外,当应用退到后台时,应该清除定时器。

 

最终实现

考虑上述种种,倒计时的实现并不简单。

我们可以封装一个自定义 Hook 来提供可复用的倒计时功能。

import { useAppState } from '@react-native-community/hooks'
import { useCallback, useEffect, useRef, useState } from 'react'
export function useCountdown(seconds = 30) {
const timer = useRef<ReturnType<typeof setInterval> | null>(null)
const [target, setTarget] = useState<Date | null>(null)
const [count, setCount] = useState<number>(0)
const appState = useAppState()
const start = useCallback(() => {
  setTarget(add(new Date(), seconds))
}, [seconds])
const stop = useCallback(() => {
  setTarget(null)
  setCount(0)
}, [])
useEffect(() => {
  if (target === null || appState !== 'active') {
    return
  }
  setCount(diff(new Date(), target))
  timer.current = setInterval(() => {
    setCount(diff(new Date(), target))
  }, 1000)
  return () => {
    if (timer.current) {
      clearInterval(timer.current)
      timer.current = null
    }
  }
}, [target, appState])
useEffect(() => {
  if (count === 0) {
    stop()
  }
}, [count, stop])
return { count, start, stop }
}
function add(date: Date, seconds: number) {
return new Date(date.getTime() + seconds * 1000)
}
function diff(now: Date, target: Date) {
return Math.max(
  Math.trunc((target.getTime() - now.getTime()) / 1000 + 0.5),
  0
)
}

 

示例

这里有一个示例,供你参考。

以上就是React Native 中实现倒计时功能的详细内容,更多关于React Native倒计时的资料请关注编程宝库其它相关文章!

 用useImperativeHandle父组件第一次没拿到子组件背景需求一个tab两个按钮A、B,默认选中的A,当点击到B时需要显示B对应的图表。考虑到 ...