I\'m trying to use the throttle
method from lodash
in a functional component, e.g.:
const App = () => {
const [value, setValue
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} />
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,
};
}
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];
};
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();
};
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)
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 />
}