0
votes

I need to make an api request when a search query param from an input fields changes, but only if the field is not empty.

I am testing with several answers found on this site, but can't get them working

Firstly this one with a custom hook

export function useDebounce(value, delay) {
  const [debouncedValue, setDebouncedValue] = useState(value);

  useEffect(() => {
    const handler = setTimeout(() => {
      setDebouncedValue(value);
    }, delay);

    return () => clearTimeout(handler);
  }, [value, delay]);

  return debouncedValue;
}

now in my component I do this

const debouncedTest = useDebounce(() => {console.log("something")}, 1000);

but this seems to gets called every rerender regardless of any parameter, and I need to be able to call it inside a useEffect, like this

useEffect(() => {
  if (query) {      
    useDebounce(() => {console.log("something")}, 1000);
  } else {
    //...
  }
}, [query]);

which of course does not work

Another approach using lodash

const throttledTest = useRef(throttle(() => {
  console.log("test");   
}, 1000, {leading: false}))

But how would i trigger this from the useEffect above? I don't understand how to make this work

Thank you

2
can u explain what you want to get out of this debounce? the api called too quickly or the button is clicked too many time ? what is the issue. Make sure you have a working code with debounce first. This way we can help u to add that in. - windmaomao

2 Answers

1
votes

Your hook's signature is not the same as when you call it.

Perhaps you should do something along these lines:

const [state, setState] = useState(''); // name it whatever makes sense
const debouncedState = useDebounce(state, 1000);

useEffect(() => {
  if (debouncedState) functionCall(debouncedState);
}, [debouncedState])
1
votes

I can quickly point out a thing or two here.

useEffect(() => {
  if (query) {      
    useDebounce(() => {console.log("something")}, 1000);
  } else {
    //...
  }
}, [query]);

technically you can't do the above, useEffect can't be nested.

Normally debounce isn't having anything to do with a hook. Because it's a plain function. So you should first look for a solid debounce, create one or use lodash.debounce. And then structure your code to call debounce(fn). Fn is the original function that you want to defer with.

Also debounce is going to work with cases that changes often, that's why you want to apply debounce to reduce the frequency. Therefore it'll be relatively uncommon to see it inside a useEffect.

  const debounced = debounce(fn, ...)
  const App = () => {
    const onClick = () => { debounced() }
    return <button onClick={onClick} />
  }

There's another common problem, people might take debounce function inside App. That's not correct either, since the App is triggered every time it renders.

I can provide a relatively more detailed solution later. It'll help if you can explain what you'd like to do as well.