DEV Community

loading...
Cover image for Let's Create a Custom Hook in React πŸ±β€πŸ‘€

Let's Create a Custom Hook in React πŸ±β€πŸ‘€

Mursal Furqan
A CS Engineering graduate with grave interest and knowledge in programming and logic building. An ML Engineer and DS with extensive hands-on experience contributing to several open-source cod
・Updated on ・3 min read

Hi all πŸ‘‹
So after quite a break, we are back with another article in the React Series with two awesome articles about hooks. If you have stumbled upon this article from a reference and don't know what hooks are, I would definitely suggest to first try our those two articles at the given link where we have discussed deeply about general Hooks in React and about some essential and Basic Hooks in react

In this article, we are about to explain how can you create a custom hook in React. Because using React this way, might really change the way you develop components πŸ˜‰ So first thing first, What are hooks? Well, the answer is here πŸ˜„. So let's just skip that part and directly jump next.

Without a custom hook

Let's imagine that we have a functionality in our component to retrieve the Window's width when the user resizes the screen. We need to know if the screen is small, medium or large.
We can write something like this:

const LayoutComponent = () => {
    const [onSmallScreen, setOnSmallScreen] = useState(false)

    useEffect(() => {
        checkScreenSize();
        window.addEventListener("resize", checkScreenSize);
    }, []);

    let checkScreenSize = () => {
        setOnSmallScreen(window.innerWidth < 700);
    };

    return (
        <div className={`${onSmallScreen ? "small" : "large"}`}>
            <h1>Hello from Default Hooks</h1>
        </div>
    );
};
Enter fullscreen mode Exit fullscreen mode

The Problem

The component works just fine. Based on the width being less than 700, it tells what the size is. But, imagine if I need the same screen size check in some other component. Should I copy-paste the code? I can! But that defeats the reusability of codes in React. Instead, we can extract this functionality inside a custom hook, and reuse it anywhere we want. πŸ’―

Creating the custom hook

Because the hooks are just JS Functions, they don't need a React component to actually exist.
I'll create a new file called useWindowsWidth.js:

import { useState, useEffect } from "react";

const useWindowsWidth = () => {
    const [isScreenSmall, setIsScreenSmall] = useState(false);

    let checkScreenSize = () => {
        setIsScreenSmall(window.innerWidth < 700);
    };

    useEffect(() => {
        checkScreenSize();
        window.addEventListener("resize", checkScreenSize);

        //Cleanup
        return () => window.removeEventListener("resize", checkScreenSize);
    }, []);

    return isSreenSmall;
};

export default useWindowsWidth;
Enter fullscreen mode Exit fullscreen mode

Using the hook

We Extracted this functionality inside useWindowsWidth function. Now, we can import it anywhere we want to use it!

import React from "react"
import useWindowsWidth from "./useWindowsWidth.js"

const MyComponent = () => {
    const onSmallScreen = useWindowsWidth();

    return (
        //Return some element
    )
}
Enter fullscreen mode Exit fullscreen mode

Now, wherever I need to know the size of the screen, I can use useWindowsWidth(). Isn't this cool? Like, rather than writing entire code from scratch, you simply import the function. You can even make this code more dynamic using props by replacing the hard-coded screen size with this.props.screenSizeCheck and woosh! You can reuse the component wherever you want, with whatever size you want.

FAQ

Do we have to start our custom hooks name with 'use'?

Well, YES! According to the official React documentation:

Unlike a React component, a custom Hook doesn’t need to have a specific signature. We can decide what it takes as arguments, and what, if anything, it should return. In other words, it’s just like a normal function. Its name should always start with use so that you can tell at a glance that the rules of Hooks apply to it.

Do same custom hooks in two components share state?

Nupp! Rest assured. If you use the same custom hooks in two components, they WILL NOT* share state.

We are Done!

Custom hooks allows you to really use your imagination when writing your React Code. You can extract and share logic in a way that was not possible with class components πŸ˜„. And yes, this also enables us to make very 'use'ful functions that can be used at different places in the application.
I wonder if you noticed the wordplay here. πŸ˜‰

Discussion (5)

Collapse
lukeshiru profile image
LUKEηŸ₯γ‚‹

Nice article! 2 things:

First: I think a better approach could be to observe changes in size in a given element, and get the DOMRect instead of just the width, you can do that with something like this:

import { useEffect, useState } from "react";

/**
 * @param {import("react").RefObject<HTMLElement>} element
 * @returns {DOMRectReadOnly | undefined}
 */
export const useResizeObserver = ({ current }) => {
    /** @type {[DOMRectReadOnly, import("react").Dispatch<DOMRectReadOnly>]} */
    const [clientRect, setClientRect] = useState();

    useEffect(() => {
        // We create a new observer...
        const observer = new ResizeObserver(
            ([{ contentRect }]) =>
                // Loop over all the properties, checking if some changed
                Object.entries(contentRect).some(
                    ([key, value]) =>
                        clientRect[key] !== value
                )
                    ? // Update the state if they did
                      setClientRect(contentRect)
                    : // Don't do anything otherwise
                      undefined
        );

        // Observe passed element
        observer.observe(current);

        // Remove observer once we are done (and every time the element changes)
        return () => observer.unobserve(current);
    }, [current]);

    return clientRect;
};
Enter fullscreen mode Exit fullscreen mode

Second: in dev.to you can enable syntax highlight in your code snippets by adding the language after the triple back-tick (more info here).

Cheers!

Collapse
mursalfk profile image
Mursal Furqan Author

Ahh... Thank you sooo much. I was looking for this <3
thnks man :)

Collapse
alekseiberezkin profile image
Aleksei Berezkin

Hooks are awesome, just imagine implementing the same with HOC πŸ˜‰ Btw checkScreenSize might be declared const and even moved to inside the effect πŸ™‚

Collapse
abazizkhoso profile image
Abdul Aziz Khoso

Thank you for simple and to the point article. :)

Collapse
hima_khaitan profile image
Himanshu

I have recently learned reactJs. You can join my discord server for collaborative projects here. Will love to have you there