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倒計時的資料請關註WalkonNet其它相關文章!
推薦閱讀:
- 如何解決React useEffect鉤子帶來的無限循環問題
- 詳解如何構建自己的react hooks
- React hooks useState異步問題及解決
- react使用useState修改對象或者數組的值無法改變視圖的問題
- React-Hook中使用useEffect清除定時器的實現方法