React

How to write your own custom React hooks

Advertisements

If you have been using react for a while, chances are you have come across the need to extract some logic into a reusable function. And with React hooks coming into the picture, doing this has become a walk in the park. We can write our own custom react hooks to abstract complex logic in a function and reuse it across components.

What is a custom React Hook?

A custom React hook is really a function that runs inside of a component. It can run other hooks or other functions inside it. These functions/hooks can be recursive too. It makes patterns like render props and higher-order components unnecessary. It is a powerful tool to have in your arsenal when writing functional components and it provides us with the following advantages:

  • Build your own hook/logic
  • Provide the ability to hook into React specific functionalities such as lifecycle and state
  • Portable logic
  • Rapid iterations

With hooks and custom react hooks in the application, we can start relying on our components to be responsible for the user interface and hooks being the piece that handles business logic.

If you have not dived into React hooks yet, we recommend checking out our previous posts about react hooks before diving into this one.

One thing to know before getting started with custom React hooks is that the function has a naming convention. The logic inside does not matter, but the function must be prefixed with the word “use”.

It is also a good idea to check out the rules of hooks post in the react docs before working with custom hooks.

This post is about understanding and writing custom react hooks, and not about what all is possible using them. The sky is the limit and a lot of the open-source community has already developed an insane number of hooks. Though they might be useful for our applications, we should know how to write our own custom React hooks since our business case related hooks would not exist.

What are we going to make?

Even though we understand that custom React hooks unleash a level of composition that is above and beyond anything we have seen before, we will build a basic custom react hook for this post. We will abstract our logic to store data in the local storage of the browser. We will also add this custom hook that we make to our local storage and react hooks example.

We will take a key as input to the hook, which will act as the key for storing the value in the local storage of the browser. We will also take in a default value for the variable that we will be creating. The hook will return a variable to the consumer and a setter to this variable as well. And anytime this variable is changed, the hook will be responsible for updating its value in local storage as well.

Thus, our hook would have the following definition:

export const useLocalStorage = (key, defaultValue) => {
  // logic to be added
  return [value, setValue]
}
JavaScript

For returning a variable that is tracked by react, we can make use of the useState react hook. Also, since we always have values in local storage as strings, we will use JSON strings to store the values and parse them on retrieval.

export const useLocalStorage = (key, defaultValue) => {
  const storedValue = JSON.parse(localStorage.getItem(key));
  const [value, setValue] = useState(storedValue || defaultValue);
  return [value, setValue]l
}
JavaScript

This takes care of returning a variable which will be tracked using react state. But we also need to update the value of the variable in local storage on every update. We will make use of the useEffect hook in our custom React hook to do so.

export const useLocalStorage = (key, defaultValue) => {
  const storedValue = JSON.parse(localStorage.getItem(key));
  const [value, setValue] = useState(storedValue || defaultValue);

   useEffect(() => {
    localStorage.setItem(key, JSON.stringify(value));
  }, [value, key]);

  return [value, setValue];
}
JavaScript

And that is sufficient for our very own custom React hook! The updated value will be reflected in local storage whenever the value changes. Whenever the hook is initialized, the value will be set to the default value if it does not exist. We will add the key to the effect’s dependencies for the sake of completeness, even though it will not get updated during the lifetime of the hook.

Using the custom react hook in our application

We can now swap the following code in our application:

const App = () => {
  const [items, setItems] = useState([]);
  const removeItem = (itemToBeDeleted) => {
    setItems(items.filter((item) => itemToBeDeleted !== item));
  };

  useEffect(() => {
    const items = JSON.parse(localStorage.getItem('items'));
    if (items) {
      setItems(items);
    }
  }, []);

  useEffect(() => {
    localStorage.setItem('items', JSON.stringify(items));
  }, [items]);

  return (
    <div className="App">
      <header className="App-header">
        To Do items
        <ItemList items={items} removeItem={removeItem} />
        <AddItemForm addItem={addItem} />
      </header>
    </div>
  );
}
JavaScript

with:

const App = () => {
  const [items, setItems] = useLocalStorage('items', []);
  const removeItem = (itemToBeDeleted) => {
    setItems(items.filter((item) => itemToBeDeleted !== item));
  };

  return (
    <div className="App">
      <header className="App-header">
        To Do items
        <ItemList items={items} removeItem={removeItem} />
        <AddItemForm addItem={addItem} />
      </header>
    </div>
  );
}
JavaScript

And it should still be working as it was before. But now we have the logic to store in the local storage abstracted in a custom React hook. And we can use this hook across multiple components wherever we wish to save to local storage.

It is important to note that custom hooks are isolated. If you use the same hook in two components, they will not share state. Therefore, we have a truly reusable piece of code that can be used across multiple components.

After reading this post, I hope you understand custom hooks in React better. Now, go ahead and start creating your own. The sky is the limit! Do leave a comment below sharing what hooks are you planning to create.

Saransh Kataria

Born in Delhi, India, Saransh Kataria is the brain behind Wisdom Geek. Currently, Saransh is a software developer at a reputed firm in Austin, and he likes playing with new technologies to explore different possibilities. He holds an engineering degree in Computer Science. He also shares his passion for sharing knowledge as the community lead at Facebook Developer Circle Delhi, NCR which is a developer community in Delhi, India.

Share
Published by
Saransh Kataria

Recent Posts

Remapping keyboard keys to avoid Carpal Tunnel

I am terrible at optimizing my keyboard layout for anything. But off lately, my little…

3 days ago

Fixing cookies are blocked for a website with shields down on Brave

I recently switched completely to the Brave browser and have set ad blocking to aggressive…

4 months ago

Generating a QR code using Node.js

I was preparing a slide deck for a hackathon and decided to put in a…

5 months ago

How to clear the global npx cache

I have been using npx a lot lately, especially whenever I want to use a…

5 months ago

Copy/Pasting output from the terminal

Manually copy-pasting the output of a terminal command with a mouse/trackpad feels tedious. It is…

6 months ago

How To Get The Hash of A File In Node.js

While working on a project, I wanted to do an integrity check of a file…

7 months ago
Advertisements