Skip to content Skip to sidebar Skip to footer

How To Debounce A Controlled Input?

I'm currently struggling with react inputs and debounce from lodash. Most of the time when I have a form I also have an edit option, so I need a controlled component to fill back t

Solution 1:

So... Apparently, there's no solution. the input takes the value from the state. While debounce prevents the state to trigger.

I made a workaround using ReactDOM.

importReactDOM from"react-dom";

exportconstsetFormDefaultValue = (obj, ref) => {
  if (ref && !ref.current) return;

  if (!obj || !obj instanceofObject) return;

  const _this = [
    ...ReactDOM.findDOMNode(ref.current).getElementsByClassName("form-control")
  ];

  if (_this.length > 0) {
    _this.forEach(el => {
      if (el.namein obj) el.value = obj[el.name];
      elseconsole.error(`Object value for ${el.name} is missing...`);
    });
  }
};

and then the use:

this.refForm = React.createRef();
setFormDefaultValue(this.state, refForm)

This way I can fill my form with the state default value and continue using debounce.

Solution 2:

Take a look at this lib: https://www.npmjs.com/package/use-debounce

Here's an example of how to use it:

importReact, { useState } from'react';
import { useDebounce } from'use-debounce';

exportdefaultfunctionInput() {
  const [text, setText] = useState('Hello');
  const [value] = useDebounce(text, 1000);

  return (
    <div><inputdefaultValue={'Hello'}
        onChange={(e) => {
          setText(e.target.value);
        }}
      />
      <p>Actual value: {text}</p><p>Debounce value: {value}</p></div>
  );
}

Solution 3:

You can try this.

importReact, { useState, useCallback, useRef, useEffect } from'react';
import _ from'lodash';

functionusePrevious(value: any) {
  const ref = useRef();
  useEffect(() => {
    ref.current = value;
  });
  return ref.current;
}

constDeboucnedInput = React.memo(({ value, onChange }) => {
  const [localValue, setLocalValue] = useState('');
  const prevValue = usePrevious(value);
  const ref = useRef();
  ref.current = _.debounce(onChange, 500);

  useEffect(() => {
    if (!_.isNil(value) && prevValue !== value && localValue !== value) {
      setLocalValue(value);
    }
  }, [value]);

  const debounceChange = useCallback(
    _.debounce(nextValue => {
      onChange(nextValue);
    }, 1000),
    []
  );

  const handleSearch = useCallback(
    nextValue => {
      if (nextValue !== localValue) {
        setLocalValue(nextValue);
        debounceChange(nextValue);
      }
    },
    [localValue, debounceChange]
  );


  return (
    <inputtype="text"value={localValue}onChange={handleSearch}
    />
  );
});

Solution 4:

At first it looks impossible, but there is a simple way to do it. Just create the debounce function expression outside the react component.

Here is a pseudo example, for modern React with Hooks:

importReact, { useState, useEffect } from"react";
import { debounce } from"lodash";
...


const getSearchResults = debounce((value, dispatch) => {
  dispatch(getDataFromAPI(value));
}, 800);



constSearchData = () => {
  const [inputValue, setInputValue] = useState("");

  ...

  useEffect(() => {
    getSearchResults(inputValue, dispatch);
  }, [inputValue]);

 ...

 return (
   <><inputtype="text"placeholder="Search..."value={inputValue}onChange={e => setInputValue(e.target.value)}
      />
      ...
   </>
 );
};

exportdefaultSearchData;

Post a Comment for "How To Debounce A Controlled Input?"