How to use throttle or debounce with React Hook?

后端 未结 17 990
甜味超标
甜味超标 2020-11-30 04:27

I\'m trying to use the throttle method from lodash in a functional component, e.g.:

const App = () => {
  const [value, setValue         


        
相关标签:
17条回答
  • 2020-11-30 05:07

    Using lodash's debounce function here is what I do:

    import debounce from 'lodash/debounce'
    
    // The function that we want to debounce, for example the function that makes the API calls
    const getUsers = (event) => {
    // ...
    }
    
    
    // The magic!
    const debouncedGetUsers = useCallback(debounce(getUsers, 500), [])
    

    In your JSX:

    <input value={value} onChange={debouncedGetUsers} />
    
    0 讨论(0)
  • 2020-11-30 05:08

    If you are using it in handler, I am fairly certain this is the way to do it.

    function useThrottleScroll() {
      const savedHandler = useRef();
    
      function handleEvent() {}
    
      useEffect(() => {
        savedHandleEvent.current = handleEvent;
      }, []);
    
      const throttleOnScroll = useRef(throttle((event) => savedHandleEvent.current(event), 100)).current;
    
      function handleEventPersistence(event) {
        return throttleOnScroll(event);
      }
    
      return {
        onScroll: handleEventPersistence,
      };
    }
    
    0 讨论(0)
  • 2020-11-30 05:08

    I'm pretty late to this, but here's a way to debounce setState()

    /**
     * Like React.setState, but debounces the setter.
     * 
     * @param {*} initialValue - The initial value for setState().
     * @param {int} delay - The debounce delay, in milliseconds.
     */
    export const useDebouncedState = (initialValue, delay) => {
      const [val, setVal] = React.useState(initialValue);
      const timeout = React.useRef();
      const debouncedSetVal = newVal => {
        timeout.current && clearTimeout(timeout.current);
        timeout.current = setTimeout(() => setVal(newVal), delay);
      };
    
      React.useEffect(() => () => clearTimeout(timeout.current), []);
      return [val, debouncedSetVal];
    };
    
    0 讨论(0)
  • 2020-11-30 05:08
    const useDebounce = (func: any) => {
        const debounceFunc = useRef(null);
    
        useEffect(() => {
            if (func) {
                // @ts-ignore
                debounceFunc.current = debounce(func, 1000);
            }
        }, []);
    
        const debFunc = () => {
            if (debounceFunc.current) {
                return debounceFunc.current;
            }
            return func;
        };
        return debFunc();
    };
    
    0 讨论(0)
  • 2020-11-30 05:08

    I do not know whether you use Redux or not -presumably not. However, I had similar problem and solved that with Saga.

    import { put, all, takeLatest } from "redux-saga/effects";
    
    const delay = (ms) => new Promise((res) => setTimeout(res, ms));
    
    function* throttledSort(e) {
      yield delay(400);
      yield put({ type: "SORT", payload: e.payload });
    }
    
    function* watchSort() {
      yield takeLatest("THROTTLED_SORT", throttledSort);
    }
    
    export default function* rootSaga() {
      yield all([watchSort()]);
    }
    

    What it precisely does is throttling dispatch of SORT action. In your component then one should use THROTTLED_SORT and not just SORT

    let throttledSort=(e) => action('THROTTLED_SORT', e.target.cellIndex);
    

    That is not precisely answer to your question but might be useful, anyway (if you think it is too far, please do not undervote)

    0 讨论(0)
  • 2020-11-30 05:09

    I use something like this and it works great:

    let debouncer = debounce(
      f => f(),
      1000,
      { leading: true }, // debounce one on leading and one on trailing
    );
    
    function App(){
       let [state, setState] = useState();
    
       useEffect(() => debouncer(()=>{
           // you can use state here for new state value
       }),[state])
    
       return <div />
    }
    
    0 讨论(0)
提交回复
热议问题