DEV Community

Cover image for How to make a Custom Hook in React
Ateev Duggal
Ateev Duggal

Posted on

How to make a Custom Hook in React

In functional components, we can do everything with the help of hooks, mainly the useState and the useEffect hook, but the power that hooks have given us has gone beyond our imagination. Here we can even make Custom Hook(s) and use them in our apps like other hooks. Pretty similar to the other hooks, these custom hooks have to follow the same rules as the other hooks do.

We will discuss everything regarding custom hooks, how they are made, rules for making custom hooks, etc in this blog.

Let’s start…

Index

  1. What are custom hooks in React?
  2. Rules to be followed by these hooks
  3. Rules for all types of hooks
  4. Why custom hook?
  5. What are we up to?
  6. Creating the React App
  7. Working on the UI part of our App
  8. Updating our App with Custom Hook
  9. Conclusion

What are Custom Hooks in React

According to the documentation, “A custom Hook is a JavaScript function whose name starts with ”use” and may call other Hooks. As both components and hooks are functions, this concept is nothing new and works fine.

In simple terms, hooks are just like components- JavaScript functions that are made to make our React App more readable and editable.

The only difference between them according to us is that the components store both logic and HTML tags or the JSX while custom hooks store only logic or a specific function that might be repeated in the app.

When it comes to creating custom hooks, the sky’s the limit. We can create any hook that we want and use it anywhere in our app while following the rules used to govern other hooks which we will discuss in the next section.

We can use any of the pre-defined hooks inside the custom hook but again we have to follow the rules as they are the basic hooks that React library has provided us with and will not work if defined or used incorrectly.

Just like in a normal hook, every time we call our custom hook the states or side-effects we have used inside it to make its logic are completely isolated or cut off from our main component. It means that once the hook is called and the logic is rendered, the states and effects will not meddle with other effects or states in the main or any other component. It is completely separated from them and will only act when it’s called.

Rules

Hooks should only be called at the top level of our app and not inside any loops, conditional statements, or functions.

  1. Hooks are a feature of functional components and should not be used in class components
  2. Every custom hook should have a prefix in its name ‘use’. It tells react that this is not a component but a hook and should follow the rules of hooks that are defined above.
  3. You cannot call hooks inside functions but custom hooks are an exception to that

Why Custom Hook in React?

Lets’ understand it this way, we divide our main component into several other components and pass states and functions between them as props to make our code more readable and understandable by not only developers but others as well.

Custom hooks work in the same way but rather than dividing the code into small pieces it is used to isolate a specific logic that we have to use at any time throughout the production of our app and call it when it’s needed in every component just by writing a single line of code. Isn’t that great?

Like a hook to fetch data from an API, we call it in any component with just a single line of code, and not bound by a specific API just by the argument url which we can change every time

But, it is not only used for separating the most used logic from the function but can also be used to separate pieces of code that might be a bit confusing without a heads up of what’s going on.

Consider a scenario, if we have a component in which we have two or more separate pieces of useEffect logic going on, it’s better to put them into separate custom hooks and name them, even if this logic will not be shared between other components.

This is because it is far easier to read and understand the logic in this way rather than reading multiple lines of strings of useEffect hook and understanding them with the component.

And as we are free to give them any name we want (starting with use), it becomes easier to understand the logic used inside that particular custom hook as just by reading the name one can tell or guess the logic inside the custom hook. We think this approach is better than explaining every line with comments.

And unlike a React component, a custom Hook doesn’t need to have a specific signature. We can decide what it takes as arguments and whether it should have return statements or not. In other words, it’s just like a normal function

Now let’s see this hook in action.

What are we up to?

Now we know the what, why, and when of the custom hook, let’s talk about the how part.

In this blog, we will make an App that fetches GIFs from a website called Giphy through its API and the Access Key which will be generated automatically as we sign up for an account and fill in the required details regarding the app.

You can visit the GitHub Repo for more details like the code or the API and also see the final product.

Creating the React App

It’s easy to create a React App – go to the working directory in any IDE and enter the following command in the terminal.

npx create-react-app custom-hook

If you are unsure how to properly set up a create-react-app project you can refer to the official guide here at create-react-app-dev.‌‌

After the setup, run npm start in the same terminal to start the localhost:3000 where our React app will be hosted. We can also see all our changes there.

Working on the UI part

For the sake of demonstrating the use of a custom hook, we have made two components fetching data from the same API, but one of them is fetching some random GIFs, while the other is fetching GIFs based on the search query using the input field as shown.

import React from "react";
import Random from "./Components/Random";
import Tag from "./Components/Tag";
const App = () => {
  return (
    <>
      <div className="container-fluid">
        <div className="row text-center mt-5">
          <div className="d-flex justify-content-center">
            <h1 className="fs-2 fw-bold p-2 w-75">Random GIF Application</h1>
          </div>
          <div className="d-flex justify-content-center mt-5">
            <Random />
            <Tag />
          </div>
        </div>
      </div>
    </>
  );
};

export default App;
Enter fullscreen mode Exit fullscreen mode

Our main reason for writing this blog is to explain the concept of custom hooks through an example, thus we will not be explaining the styling part of our app.

The Random Component

This component, as told, will fetch random data from Giphy’s API and display it using the img tag in our app.

As always the API will be called inside the useEffect hook which will be called at the top level of our app and used as per the rules of Hooks. The code is as follows-

import React, { useState, useEffect } from "react";

const API_KEY = process.env.REACT_APP_API_KEY;

const Random = () => {
  const [gif, setGif] = useState("");

  const fetchGif = async () => {
    const initial = await fetch(
      `https://api.giphy.com/v1/gifs/random?api_key=${API_KEY}`
    );
    const data = await initial.json();
    const final = data.data.images.downsized_large.url;
    setGif(final);
  };

  useEffect(() => {
    fetchGif();
  }, []);

  const newGif = () => {
    fetchGif();
  };
return (
    <>
      <div className="container-fluid">
        <div className="row">
          <div className="d-flex justify-content-center">
            <h1 className="fs-2 fw-bold p-2 w-75">Random GIF</h1>
          </div>
          <figure className="w-100 mt-4">
            <img src={gif} alt="random gifs" className="w-75" />
          </figure>
          <div className="d-flex justify-content-center my-4">
            <button
              className="text-center fs-5 fw-bold text-capitalize px-4 btn-secondary text-white py-2"
              onClick={newGif}
            >
              New Random Gif
            </button>
          </div>
        </div>
      </div>
    </>
  );
};

export default Random;
Enter fullscreen mode Exit fullscreen mode

In the above code, we have a file ‘.env’ in which we have stored our Access_Key which we are dynamically getting in our Random Component.

We have initialized the state as an empty string with its updating function using the useState hook for fetching and storing the fetched GIF in it and displaying it in our App.

There are many methods in both JavaScript and React through which we can make an API call and fetch the data into the state we have already made and discussed above.

In the UI part of our APP, we have an h1 tag, an image tag, and a button with an onClick event handler which will trigger the fetchGIF() function to make the API call and get the random GIF which will be displayed using the img tag.

The Query Component

In this component, everything’s the same except for the additional parameter in the API and the input tag with the value attribute, and the onChange() event handler in the UI part of the component.

As told, this component will not fetch random GIFs, it will fetch query-based GIFs which will be stored and used using the input tag and the value attribute with the onChange event handler as told.

import React, { useState, useEffect } from "react";

const API_KEY = process.env.REACT_APP_API_KEY;

const Query = () => {
  const [query, setQuerry] = useState("dogs");
  const [gif, setGif] = useState("");

  const fetchGif = async () => {
    const initial = await fetch(
      `https://api.giphy.com/v1/gifs/random?api_key=${API_KEY}&tag=${query}`
    );
    const data = await initial.json();
    const final = data.data.images.downsized_large.url;
    setGif(final);
  };

  useEffect(() => {
    fetchGif();
  }, []);

  const newGif = () => {
    fetchGif();
  };
return (
    <>
      <div className="container-fluid">
        <div className="row">
          <div className="d-flex justify-content-center">
            <h1 className="fs-2 fw-bold p-2 w-75 text-capitalize">
              Randon {tag} GIFs
            </h1>
          </div>
          <figure className="w-100 mt-4">
            <img src={gif} alt="random gifs" className="w-75" />
          </figure>
          <div className="d-flex justify-content-evenly my-4">
            <input
              type="text"
              value={query}
              onChange={(e) => setQuerry(e.target.value)}
              className="text-center fs-5 fw-bold text-capitalize py-2 border-0"
            />
            <button
              className="text-center fs-5 fw-bold text-capitalize px-4 btn-secondary text-white"
              onClick={newGif}
            >
              New {tag} GIF
            </button>
          </div>
        </div>
      </div>
    </>
  );
};

export default Query;
Enter fullscreen mode Exit fullscreen mode

The output will be as below

Result

Continue Reading.

Top comments (1)

Collapse
 
lestermauldin profile image
Info Comment hidden by post author - thread only accessible via permalink
LesterMauldin

Can we create custom Hooks in React? Black magic to break marriage

Some comments have been hidden by the post's author - find out more