Davtho1983
Davtho1983

Reputation: 3954

React hooks - prevent useEffect from updating too fast

I have a datepicker component I'm making. There are three 'dials', for days, months and years, which are moved by dragging the mouse within column divs. It works great, except it updates really fast and the whole thing moves too quickly. How do I make sure it updates only at set intervals?

My useEffect code is:

    useEffect(() => {
            if (mouseState.mouseIsDown && mouseState.dateField === 'year') {
                getYear();
            } else if (date) {
                setNewStartDate();
            }

            if (mouseState.mouseIsDown && mouseState.dateField === 'month') {
                getMonth();
            } else if (date) {
                setNewStartDate();
            }

            if (mouseState.mouseIsDown && mouseState.dateField === 'day') {
                getDay();
            } else if (date) {
                setNewStartDate();
            }
        },
        [ mouseState.mouseIsDown, mouseState.dateField, endPositionYYear, endPositionYMonth, endPositionYDay ]
    );

My getYear function is like so:

    const getYear = () => {
            getPositions('year');
            if (startDate.getFullYear() >= 1911 || (endPositionYYear < 0 && startDate.getFullYear() === 1911)) {
                if (endPositionYYear > prevEndPositionYYear) {
                    setMyDate(new Date(year - 1, month, day));
                } else {
                    setMyDate(new Date(year + 1, month, day));
                }
            } else if (startDate.getFullYear() < 1911 && endPositionYYear > 0) {
                setMyDate(new Date(year + Math.round(endPositionYYear / 10), month, day));
            }
        };

If I set Timeouts during the getYear function, the useEffect hook with receive new Y position coordinates from mouseState.mouseIsDown, which stores the Y coordinates of the mouse while the left mouse button is down, before the timeout has elapsed, and the function call will be overridden by the latest call to getYear? I think?

Is there any way of making sure getYear only gets called every 500ms say?

Upvotes: 0

Views: 975

Answers (1)

Cenk &#199;etinkaya
Cenk &#199;etinkaya

Reputation: 139

You can improve by your needs.

// 0 is no limit
function useDebounce(callFn, callCount = 0 , time = 1000){
  const timeout = useRef(); // to clear interval in anywhere
  const counter = useRef(0);


  function clear(){
    timeout.current && clearInterval(timeout.current);
    counter.current = 0;
  }

  useEffect(() => {
    timeout.current = setInterval(() => {
      callFn(counter.current++); // pass call-count, it may be useful
      if(callCount > 0 && counter.current == callCount){
        timeout.current && clearInterval(timeout.current);
      }
    }, time);
    return clear
  }, []);

  return useCallback(() => clear(), []);
}

Upvotes: 1

Related Questions