Skip to content

useRafState

作用

只在 requestAnimationFrame callback 时更新 state,一般用于性能优化

原理

requestAnimationFrame 告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行。

源码

ts
import { useCallback, useRef, useState } from 'react'
import type { Dispatch, SetStateAction } from 'react'
import useUnmount from '../useUnmount'

// 函数重载 参数可能是函数,也可能是值,也可能没有传默认值
function useRafState<S>(initialState: S | (() => S)): [S, Dispatch<SetStateAction<S>>]
function useRafState<S = undefined>(): [S | undefined, Dispatch<SetStateAction<S | undefined>>]

function useRafState<S>(initialState?: S | (() => S)) {
  // 用来缓存requestAnimationFrame
  const ref = useRef(0)
  // 用来缓存state,默认是初始化的值
  const [state, setState] = useState(initialState)

  // 用来更新state
  const setRafState = useCallback((value: S | ((prevState: S) => S)) => {
    // 先取消上一次的requestAnimationFrame
    cancelAnimationFrame(ref.current)

    // 重新赋值
    ref.current = requestAnimationFrame(() => {
      setState(value)
    })
  }, [])

  // 组件卸载时,取消requestAnimationFrame
  useUnmount(() => {
    cancelAnimationFrame(ref.current)
  })

  // 返回state和更新state的函数
  return [state, setRafState] as const
}

export default useRafState

如有转载或 CV 的请标注本站原文地址