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?"