react中如何实现让一个值成为节流的响应式的值

162 阅读1分钟

之前有被问过,你如何实现让一个值成为节流的响应式的值

useThrottleState

  • 使用
    const [value, setValue] = useThrottleState(0, 1000)
  • 实现
import { useEffect, useState, useRef } from "react";

function useThrottleState(initValue, delay = 200) {

    const [, update] = useState({})
    const value = useRef(null);
    const timer = useRef(null);

    useEffect(() => { value.current = initValue; }, [])

    const throttle = (val) => {
        value.current = val;
        if (timer.current) {
            return
        }
        timer.current = setTimeout(() => {
            update({})
            timer.current = null
        }, delay)
    }

    const dispatch = (val) => {
        console.log('dispatch', val);
        throttle(val)
    }

    return [value.current, (val) => dispatch(val)]
}


export default useThrottleState

扩展:实现一个节流的Effect hook

useThrottleEffect

  • 使用
  const { cancel } = useThrottleEffect(() => {
    console.log('useThrottleEffect执行');
  }, 1000, [num])
  • 实现
import { useEffect, useRef } from "react";


function useThrottleEffect(callback, delay = 200, deps) {

    const timer = useRef(null)

    useEffect(() => {
        if (timer.current) return
        timer.current = setTimeout(() => {
            callback()
            clearTimeout(timer.current)
            timer.current = null;
        }, delay)
    }, deps)

    /**
     * @cancel 强行终止当前fn执行
     */
    const cancel = () => {
        clearTimeout(timeout.current)
        timer.current = null
    }

    return { cancel }
}


export default useThrottleEffect