React Custom Hooks -> Make your own custom hook.

React Custom Hooks -> Make your own custom hook.

With the introduction of React 16.8, we were introduced to React Hooks. This introduced a paradigm shift into the developer world of React. Since then a lot of people have moved from Class-based components to functional components and made use of React Hooks.

Now that React hooks are almost everywhere and the new standard for React developers. Let's venture into the world of custom hooks.

P.S This article does assume that you have knowledge of React and React hooks

What are custom hooks

Custom hooks are in all simplicity, just functions. Now the naming of these functions starts with the word use but that's the naming convention. Unlike a component, a custom hook does not need to follow a pattern, we decide what we want as arguments, and what we return, simply like functions.

Custom hooks allow us to access all React hooks and make a custom function suitable to our useCase (read use-case). This mechanism has a lot of advantages in terms of abstraction, reusability, and separation of logic.

Why custom hooks

When we want to share logic between two JavaScript functions, we extract it to a third function. Both components and Hooks are functions, so this works for them too! - React Docs

The main reason to use a custom hook is reusability. If you find yourself using a React hook multiple times for the same functionality, this can be extracted as a custom hook. This saves you a lot of code duplication and makes for better code readability. Also makes code and logic a lot more manageable as now you only have to change one file as opposed to changing logic everywhere.

Now that I've made my case for using Custom Hooks, let's dive into an example.

Custom Hook for API calls

API calls are something we React developers use a lot. Now in ideal conditions, an API call in React requires some state management and some hooks. Hooks like useState, useEffect even useReducer are used to manage API calls and the data/errors that they return.

Here we are using a simple API that just fetches a list of types of coffee. Coffee-API

CPT2205291526-564x398.gif

export default function App() {
  useEffect(() => {
    setStatus("loading");
    setTimeout(() => {
      fetch("https://api.sampleapis.com/coffee/hot")
        .then((res) => res.json())
        .then((data) => {
          setCoffeeList(data);
          setStatus("success");
        })
        .catch((err) => setStatus("error"));
    }, 1000);
  }, []);
  const [coffeeList, setCoffeeList] = useState([]);
  const [status, setStatus] = useState("idle");
  if (status === "error") return <p>Some error occured</p>;
  if (status === "loading") return <p> Loading </p>;
  return (
    <div className="App">
      <ul>
        {coffeeList.map((item) => (
          <li key={item.title}>{item.title}</li>
        ))}
      </ul>
    </div>
  );
}

We are using 2 hooks to manage the state and display the output here

  • useEffect -> To call the API to fetch a list of types of coffee.
  • useState -> To manage the state of the list of coffee and to manage loading states of the API to display appropriate messages for the user.

Note : We are using setTimeout just to delay the API call so that we can record the loading state in the frame

This approach in itself is correct and fine, but now imagine your app gets complex and you make more such requests in other components. That would lead to the repetition of code in every component while the basic functionality remains the same. This can be solved by using a custom hook.

CPT2205291544-729x398.gif

useHttp.js

export const useHttp = (url) => {
  const [status, setStatus] = useState("idle");
  const [data, setData] = useState([]);
  useEffect(() => {
    setStatus("loading");
    setTimeout(() => {
      fetch(url)
        .then((res) => res.json())
        .then((data) => {
          setData(data);
          setStatus("success");
        })
        .catch((err) => setStatus("error"));
    }, 1000);
  }, [url]);
  return { status, data };

App.js

export default function App() {
  const { data, status } = useHttp("https://api.sampleapis.com/coffee/hot");
  if (status === "error") return <p>Error</p>;
  if (status === "loading") return <p>Loading</p>;
  return (
    <div className="App">
      <p>Using a custom hook</p>
      <ul>
        {data.map((item) => (
          <li key={item.title}>{item.title}</li>
        ))}
      </ul>
    </div>
  );

As you will notice, the output is the same, but now we have extracted the loading state and data fetching into a hook. This makes this logic and states reusable. Wherever we need to fetch something again, we can just call this hook, and voila, we get the loading state and the data easily.

This example just illustrates just how powerful and easy using custom hooks can be in your React application.

If you want more information on the code. Visit this codesandbox-example and fork it to play around with it and explore more power into custom hooks.

Thanks for taking the time to read this article. If this article helps you in your journey as a React/JavaScript developer leave a ❤️ with your comments and suggestions. Thank You!