Creating your first custom hook in react

Creating your first custom hook in react

Hooks

Hooks let use state and other features in a functional react component. You might have come across at least a few of them for eg. useState, useEffect, useCallback etc. In this blog post will try to make our own custom hook and use it our react?

Custom Hook

A Custom Hook is a JavaScript function whose name starts with ”use” and that may call other Hooks. There are 3 major rules of the hook to be followed as below

  1. Hook should be called inside React Component or Hooks.
  2. Hooks should be called at the top level of the component or hook, nesting of hooks is not permitted.
  3. The name of the hook should start with the word "use" in lowercase.

Problem

We have a small counter application, which has a count state, increment button, and a decrement button to update the count state. We would like to implement a functionality that saves the count to the local storage so it's not lost on reload/refresh of the page

Solution

1) let's start by implementing the above solution using useState & useEffect hook

import React from "react";

export default function App() {

let [count, setCount] = React.useState( localStorage.getItem('count') || 0);

React.useEffect(() => {
    localStorage.setItem('count', count);
}, [count]);

return (
    <div className="App">

     <button onClick={() => { setCount(count - 1) }}>
        Decrement
      </button>

      &emsp;

      {count} 

      &emsp;

      <button onClick={() => { setCount(count + 1) }}>
        Increment
      </button>
    </div>
  );
}

2) Let's create a custom hook useSyncStateToLocalStorage to combine both the useState hook and useEffect hook usage from the above example in a single useSyncStateToLocalStorage hook

import React from "react";

export default function App() {

let [count, setCount] = useSyncStateToLocalStorage();

return (
    <div className="App">

     <button onClick={() => { setCount(count - 1) }}>
        Decrement
      </button>

      &emsp;

      {count} 

      &emsp;

      <button onClick={() => { setCount(count + 1) }}>
        Increment
      </button>
    </div>
  );
}

function  useSyncStateToLocalStorage(){
    let [count, setCount] = React.useState( localStorage.getItem('count') || 0);

    React.useEffect(() => {
       localStorage.setItem('count', count);
    }, [count]);

   return [count, setCount];
}

3) But our useSyncStateToLocalStorage custom hook is tied to the count state, let's make it reusable, by adding a key argument and initialState argument

function  useSyncStateToLocalStorage(key, initialState){

    let [value, setValue] = React.useState( localStorage.getItem(key) || initialState);

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

   return [value, setValue];
}

4) Let's use or modified hook in our application

let [count, setCount] = useSyncStateToLocalStorage('count', 0);

To Summarize

  1. Custom hooks are nothing but functions and their name starts with the 'use' keyword.
  2. Hooks or Custom hooks should be called inside a react component or other hooks only.
  3. Hooks should be called at the top level of the component or hook.
  4. Nesting of hooks is not allowed.