Most Awesome Hooks for your React project

Subscribe to my newsletter and never miss my upcoming articles

React.js is currently one of the most popular JavaScript libraries for front-end developers.

React really changed the way we build Single-page applications (SPAs). One of its greatest features is hooks that introduced in React 16.8 and that new feature enables the possibility of using functional components instead of class components handling the state with the Hooks.

React offers ways to implement our own custom hooks. Some awesome custom hooks are:

useTimeout Hook

With this custom hook, we can implement a javascript setTimeout using a declarative approach.

Code

import { useEffect, useRef } from 'react';

const useTimeout = (callback, timeout) => {
  const savedCallback = useRef(null);
  savedCallback.current = callback;

  useEffect(
    () => {
      savedCallback.current = callback;
    },
    [callback]
  );

  useEffect(
    () => {
      if (timeout) {
        const timeoutId = setTimeout(() => {
          savedCallback.current();
        }, timeout);
        return () => clearTimeout(timeoutId)
      }
    },
    [timeout]
  )
}

Example of use

import { useState } from 'react';

const ExampleComponent = () => {
  const [message, setMessage] = useState('');
  useTimeout(() => {
    setMessage('Hello World');
  }, 7500);

  return (<p>{message}</p>);
}

usePrevious Hook

With this custom hook, we can have access to the previous state related to the components.

Code

import { useEffect, useRef } from 'react';

const usePrevious = (state) =>  {
  const ref = useRef();

  useEffect(() => {
    ref.current = state;
  });

  return ref.current;
}

Example of use

import { useState } from 'react';

const ExampleComponent = () => {
  const [counter, setCounter] = useState(0);
  const previousCounter = usePrevious(counter);

  return (
   <>
     <p>
       Counter: {counter}
       Previous Counter: {previousCounter}
     </p>
     <button onClick={() => setCounter(counter +1)}>
       Next
     </button>
   </>
  );
}

useInterval Hook

With this custom hook, we can implement javascript setInterval using a declarative approach.

Code

import { useEffect, useRef } from 'react';

const useInterval = (callback, delay) => {
  const savedCallback = useRef(null);
  savedCallback.current = callback;

  useEffect(
    () => {
      savedCallback.current = callback;
    },
    [callback]
  );

  useEffect(
    () => {
      if (delay) {
        const intervalId = setInterval(() => {
          savedCallback.current();
        }, delay);
        return () => clearInterval(intervalId)
      }
    },
    [delay]
  )
}

Example of use

import { useState } from 'react';

const ExampleComponent = () => {
  const [seconds, setSeconds] = useState(0);
  useInterval(() => {
    setSeconds(seconds + 1);
  }, 1000);

  return (<p>{seconds}</p>);
}

useFetch Hook

The useFetch hook can be used to implement fetch in a declarative way. Also, this custom hook helps with behaviors as loading and errors.

Code

import { useState, useEffect } from 'react';

const useFetch = (initialUrl, initialOptions = {}) => {
  const [url, setUrl] = useState(initialUrl);
  const [options, setOptions] = useState(initialOptions);
  const [data, setData] = useState(null);
  const [error, setError] = useState(null);
  const [isLoading, setIsLoading] = React.useState(false);

  useEffect(() => {
    const fetchData = async() => {
      try {
        setIsLoading(true);
        const response = await fetch(url, options);
        const json = await response.json();
        setData(json);
      } catch {
        setError(error);
      } finally {
        setIsLoading(false);
      }
    }
    fetchData();
  }, [url, options]);

  return ({data, error, isLoading, setUrl, setOptions});
};

Example of use

import { useState } from 'react';

const URL = 'https://jsonplaceholder.typicode.com/todos';

const ExampleComponent = () {
  const { data, error, isLoading } = useFetch(URL);

  if(isLoading) {
    return (<p>Loading...</p>)
  }

  return (
      <p>{error?.message || JSON.stringify(data)}</p>
  );
}

useContructor hook

The useContructor hook can be used to implement the same behavior as class components.

Code

import React from 'react';

export const useConstructor = (callBack = () => {}) => {
  const [hasBeenCalled, setHasBeenCalled] = React.useState(false);
  if (hasBeenCalled) return;
  callBack();
  setHasBeenCalled(true);
};

I will be updating the post with new awesome Hooks

Edidiong Asikpo's photo

Oh nice, I haven't used most of these hooks yet. But I will definitely check it out.

Thanks for sharing, Brayan Arrieta Alfaro.

Patryk Eliasz's photo

Do you have any example of useContructor hook usage?

Brayan Arrieta Alfaro's photo

I will try to add an example when have some time