Debounce in React.js

## The Problem

Imagine you are creating an input field that pings an API every time the user types something. If the user types "Hello there!", the API will be pinged 11 times! In all likelihood, you only want to call the API once the user has stopped typing. So how can this be achieved in React?

## The Solution

The solution is something called debouncing. In simple terms, you set a timer when the user starts typing, and the timer restarts every time the user types something new. The API is only called once the timer has the chance to go off, meaning the user has probably stopped typing.  

## Creating a Custom Hook

In the code below, we'll be creating our custom `useDebounce hook`. You can learn more about creating custom hooks [here](https://reactjs.org/docs/hooks-custom.html). 

If you copy and paste this example, make sure to add the correct API endpoint and handle the response object appropriately. 

## The Code

``` App.jsx
import { useEffect } from "react";
import { useState } from "react";

const App = () => {
  const [text, setText] = useState("");
  const debouncedValue = useDebounce(text, 500);

  const handleChange = (e) => {
    setText(e.target.value);
  };

 //The API I am using requires on the first letter to be uppercase
  const capitalize = (string) => {
    //make all to Lowercase
    const lowercaseString = string.toLowerCase();
    const capitalizedString =
      lowercaseString.slice(0, 1).toUpperCase() + lowercaseString.slice(1);
    return capitalizedString;
  };

  useEffect(() => {
//I'm using a Lord of the Rings API but feel free to use
//a different one.
//Also, make sure to create an .env file at the root of your project
//and save you API key there if needed.
// React env varaibles must start with REACT_APP
    const fetchData = async () => {
      if (debouncedValue !== "") {
        //fetch info on LOTR character
        try {
          const res = await fetch(
            `https://the-one-api.dev/v2/character?name=${capitalize(
              debouncedValue
            )}`,

            {
              method: "GET",
              withCredentials: true,
              headers: {
                Authorization: `Bearer ${process.env.REACT_APP_API_KEY}`,
              },
            }
          );
          const data = await res.json();
          console.log(data);
        } catch (err) {
          console.log("error:", err);
        }
      }
    };
    fetchData();
  }, [debouncedValue]);

//I used the classname to add styling in a seperate 
//App.css file (not included in this tutorial).
  return (
    <div className="debounce">
      <h2>Debounce</h2>
      <input type="text" value={text} onChange={(e) => handleChange(e)} />
    </div>
  );
};

export default App;

// useDebounce hook
// value: the input value from the user
// delay: how long to wait in milliseconds
const useDebounce = (value, delay) => {
  const [debouncedValue, setDebouncedValue] = useState(value);

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

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

  return debouncedValue;
};
```

And there you have it, a simple way to optimize your React application by cutting back on unnecessary API calls.