Custom React Hooks
Oct 29, 2020 • 🍻 00min 44s read
🔖 reactreact hooks
useDeepCompareCallback
¶Deep compare version of React.useCallback
useDeepCompareCallback.ts | 24 lines.
123456789101112131415161718192021222324import { isEqual } from '@guanghechen/equal'import type React from 'react'import { useCallback, useRef } from 'react'
/** * Deep compare version of React.useCallback * @param fn * @param deps */export function useDeepCompareCallback<T extends (...args: any[]) => any>( fn: T, deps: React.DependencyList,): T { const signal = useRef<number>(0) const prevDeps = useRef<React.DependencyList>(deps)
if (!isEqual(prevDeps.current, deps)) { signal.current += 1 } prevDeps.current = deps
// eslint-disable-next-line react-hooks/exhaustive-deps return useCallback(fn, [signal.current])}
useDeepCompareEffect
¶Deep compare version of React.useEffect
useDeepCompareEffect.ts | 21 lines.
123456789101112131415161718192021import { isEqual } from '@guanghechen/equal'import type React from 'react'import { useEffect, useRef } from 'react'
/** * Deep compare version of React.useEffect * @param fn * @param deps */export function useDeepCompareEffect(fn: React.EffectCallback, deps: React.DependencyList): void { const signal = useRef<number>(0) const prevDeps = useRef<React.DependencyList>(deps)
if (!isEqual(prevDeps.current, deps)) { signal.current += 1 } prevDeps.current = deps
// eslint-disable-next-line react-hooks/exhaustive-deps useEffect(fn, [signal.current])}
useDeepCompareMemo
¶Deep compare version of React.useMemo
useDeepCompareMemo.ts | 21 lines.
123456789101112131415161718192021import { isEqual } from '@guanghechen/equal'import type React from 'react'import { useMemo, useRef } from 'react'
/** * Deep compare version of React.useMemo * @param fn * @param deps */export function useDeepCompareMemo<T>(fn: () => T, deps: React.DependencyList): T { const signal = useRef<number>(0) const prevDeps = useRef<React.DependencyList>(deps)
if (!isEqual(prevDeps.current, deps)) { signal.current += 1 } prevDeps.current = deps
// eslint-disable-next-line react-hooks/exhaustive-deps return useMemo(fn, [signal.current])}
useInterval
¶Execute callback interval in react function components.
userInterval.ts | 25 lines.
12345678910111213141516171819202122232425import { useEffect, useRef } from 'react'
type Callback = () => void
/** * Execute callback interval in react function components. * @param callback * @param delay */export function useInterval(callback: Callback, delay: number): void { const callbackRef = useRef<Callback>(callback)
useEffect(() => { callbackRef.current = callback }, [callback])
useEffect(() => { const tick: Callback = () => { if (callbackRef.current === undefined) return callbackRef.current() } const id = setInterval(tick, delay) return () => clearInterval(id) }, [delay])}
usePreviousState
¶记录上一个状态。
利用更新 ref.current
的值不会触发组件更新的特性,在 usePreviousState
中总是返回旧的值,尽管在 userPreviousState
的 useEffect
中更新了新值,但并不触发更新。
usePreviousState.ts | 14 lines.
1234567891011121314import { useEffect, useRef } from 'react'
/** * Use previous state. * @param value * @returns */export function usePreviousState<T = unknown>(value: T): T { const ref = useRef<T>(value) useEffect(() => { ref.current = value }, [value]) return ref.current}
useReactiveRef
¶useReactiveRef.ts | 15 lines.
123456789101112131415import type React from 'react'import { useEffect, useRef } from 'react'
/** * Create a reactive ref which will follow the changes of the given data. * @param data * @returns */export function useReactiveRef<T>(data: T): React.MutableRefObject<T> { const ref = useRef(data) useEffect(() => { ref.current = data }, [data]) return ref}
Example
¶demo/usePreviousState.jsx
Related
¶