Understanding React Custom Hooks

Understanding React Custom Hooks

With an example to know how to build Custom Hooks

What are Custom Hooks?

Custom hooks are Javascript functions whose name starts with the word use and that may call other Hooks inside them as well. They are created when one wants to reuse the code in several parts of the app and also wants to tidy up the components and isolate the logic from the view.

It is mandatory to start the name of the Custom Hook with the word use, e.g. useLocalStorage, useDocumentTitle etc.

Custom hooks are equivalent to React Hooks and thus, all the rules of the React Hooks are applicable to them as well like:

  • CALL Hooks only at the TOP LEVEL (and not inside loops, conditions or nested functions)
  • CALL Hooks only from REACT FUNCTIONS (and not from Regular Javascript Functions)

  • Hooks can call other Hooks as well

How to create a Custom Hook?

Custom hooks are created in the same as any JS function. They are nothing but a simple refactoring of the code into a separate function to make it reusable.

Let's understand this through an Example!

Consider the following example where we are using the useEffect hook to update the document title.

import { useEffect, useState } from "react";
import "./styles.css";

export default function App() {
  const [counter, setCounter] = useState(0);

  useEffect(() => {
    document.title = counter;
  }, [counter]);

  return (
    <div className="App">
      <h2>Understanding Custom Hooks</h2>
      <h3>Changing Document-title using Custom Hook</h3>

      <div> Count is: {counter} </div>
      <button
        style={{ margin: "0.2rem" }}
        onClick={() => setCounter((prev) => prev + 1)}
      >
        Increment
      </button>
    </div>
  );
}

Here's a simple state variable - counter. On the click of the increment button, its value gets increased by 1 by the setCounter function.

The useEffect hook sets the title of the document to the value of the counter using document.title = counter. Whenever, the counter value is changed the useEffect gets triggered, because of the presence of the counter variable in it's dependency array.

12.PNG

Creating a Custom Hook

Creating a Custom Hook out of the above code is just a simple refactoring of the code. Let us see how...

import { useEffect, useState } from "react";
import "./styles.css";

const useDocumentTitle = (counter) => {
  useEffect(() => {
    document.title = counter;
  }, [counter]);
};

export default function App() {
  const [counter, setCounter] = useState(0);
  useDocumentTitle(counter);

  return (
    <div className="App">
      <h2>Understanding Custom Hooks</h2>
      <h3>Changing Document-title using Custom Hook</h3>

      <div> Count is: {counter} </div>
      <button
        style={{ margin: "0.2rem" }}
        onClick={() => setCounter((prev) => prev + 1)}
      >
        Increment
      </button>
    </div>
  );
}

Now to create a custom hook, we have just bulit a JS function called useDocumentTitle(counter) and extracted out the useEffect() code into the custom hook function. Like any other hook, custom hook also needs to be called. Thus calling the custom hook using useDocumentTitle(counter) inside the body of the functional component App().

This custom hook can also be extracted out into a different file and then imported to use it in our App component. And you will see our app will work in the exact same way with the help of the custom hook useDocumentTitle(counter).

It is clearly visible, how clean the code looks after a simple refactoring by extracting out the logic part from the view and converting it into a custom hook.

Thus make use of the Custom Hooks as much as possible in order to tidy up your code and make it reusable with the help of custom hooks.

And that's it.

Checkout the codesandbox for the source code.

Hope you understood the concept of Custom Hooks with this simple example.

Thank you for reading.

This is my first blog on hashnode. Your feedback would be highly appreciated