mark
mark

Reputation: 245

Lodash debounce isn't preventing dispatch as expected onChange

Currently, I have a list of checkboxes that onChange will make a request to the server to return some data. However, I am using lodash debounce to try and make a request only when the user has stopped selecting the multi-checkbox after a certain amount of time.

Currently, it prevents dispatching straight away but will dispatch after the debounce time has met rather when the user has stopped interacting with the checkboxes. Can someone tell me how I would achieve this or where I am going wrong?

Thanks!

import React, { useContext, useState, useEffect } from 'react';
import { Context } from '../../pages/search-and-results/search-and-results.js';
import debounce from 'lodash.debounce';

const FilterCheckbox = ({ name, value }) => {
  const checkboxContext = useContext(Context);
  const [checked, setChecked] = useState(false);
  const debounceCheckboxSelection = debounce(dispatchCheckbox, 2000);

  function dispatchCheckbox(type, value) {
    checkboxContext.dispatch({
      type: type,
      payload: { value }
    });
  }

  return (
    <Label>
      <FilterInput
        type="checkbox"
        name={name}
        onChange={() => {
          if (checked) {
            debounceCheckboxSelection('REMOVE_SELECTED_PROPERTY_TYPE', value);
            setChecked(false);
            return;
          }
          debounceCheckboxSelection('SET_SELECTED_PROPERTY_TYPE', value);
          setChecked(true);
        }}
        checked={checked}
      />
      {name}
    </Label>
  );
};

export default FilterCheckbox;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

Upvotes: 3

Views: 1498

Answers (2)

kyorilys
kyorilys

Reputation: 832

   <input onChange={_.debounce((e)=> dispatch(search(e.target.value)), 300)} />

Can do something like this and remember to import the lodash and dispatch

Upvotes: 0

Ajeet Shah
Ajeet Shah

Reputation: 19823

Your debounced function is getting created at each re-render, to fix it:

You can use useRef which returns a ref object which will persist for the full lifetime of the component:

const debounceCheckboxSelection = useRef(
  debounce(dispatchCheckbox, 2000);
)

and access its initial value with debounceCheckboxSelection.current:

<FilterInput
  type="checkbox"
  name={name}
  onChange={() => {
    if (checked) {
      debounceCheckboxSelection.current('REMOVE_SELECTED_PROPERTY_TYPE', value);
      setChecked(false);
      return;
    }
    debounceCheckboxSelection.current('SET_SELECTED_PROPERTY_TYPE', value);
    setChecked(true);
  }}
  checked={checked}
/>

Or you can use useCallback will returns a memoized version of the callback that only changes when any of its dependencies change:

const debounceCheckboxSelection = useCallback(
  () => debounce(dispatchCheckbox, 2000), []
)

Upvotes: 2

Related Questions