Skip to content Skip to sidebar Skip to footer

Why My Debounce Functionality Is Not Working In A React App With Hooks?

My goal is to fire a fetch request to get data from an API after some delay. In my particular case, I have an input field where a user can input a post ID. I don't want fire a fetc

Solution 1:

The main issue here is that you are calling the function only when input != "". Till then input is not set to the desired value and thus the function becomes a no-op. This change will however help

import { useCallback, useEffect, useState } from'react'import'./App.css'functiondebounce(fn, ms) {
  let timeoutId
  returnfunction (...args) {
    if (timeoutId) clearTimeout(timeoutId)
    timeoutId = setTimeout(() => {
      fn(...args)
    }, ms)
  }
}

exportdefaultfunctionApp() {
  const [input, setInput] = useState('')

  consthandleInputChange = (e) => {
    setInput(e.target.value);
    debouncedFireRequest(e.target.value);
  };

  const debouncedFireRequest = useCallback(
    debounce(async (value) => {
      if (value !== '') {
        let res = awaitfetch(`https://jsonplaceholder.typicode.com/posts/${value}`)
        let resData = await res.json()
        console.log(resData)
      }
    }, 1000),
    []
  );

  return (
    <divclassName='App'><inputtype='text'onChange={handleInputChange}value={input}></input></div>
  );
}

Solution 2:

Try this:

useEffect(() => {
    const apiCallTimeoutId = setTimeout(() => {
      fireRequest()
    }, 1000);
    return() =>clearTimeout(apiCallTimeoutId);
  }, [input]);

1 sec after the user stops typing the request will be fired.

Solution 3:

This answer is on the right track but there's no need to keep const fireRequest = useCallback(debounce(fetchData, 1000), []) as it seems to imply.

Just fire the timeout, then clear it in the useEffect cleanup callback if the component rerenders:

<scripttype="text/babel"defer>const {useState, useEffect} = React;

constExample = () => {
  const [input, setInput] = useState("");
  const [result, setResult] = useState();

  const fetchData = async () => {
    if (input) {
      try {
        const res = awaitfetch(`https://jsonplaceholder.typicode.com/posts/${input}`);
        
        if (res.ok) {
          setResult(await res.json());
        }
      }
      catch (err) {
        console.error(err);
      }
    }
  }

  useEffect(() => {
    const timeout = setTimeout(fetchData, 1000);
    return() =>clearTimeout(timeout);
  }, [input]);

  return (
    <div><inputplaceholder="type a small number, e.g. 12"onChange={e => setInput(e.target.value)} 
        value={input}
      />
      {result && <div>{result.title}</div>}
    </div>
  );
};

ReactDOM.render(<Example />, document.body);

</script><scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.26.0/babel.min.js"></script><scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script><scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>

Note the try-catch on the fetch call and checking res.ok rather than throwing when res.json() fails.

Post a Comment for "Why My Debounce Functionality Is Not Working In A React App With Hooks?"