Understanding React custom Hooks

In React there are several built-in Hooks like useState, useEffect, and useContext. Sometime you need to create your own Hooks for specific purpose like checking user session, fetching data, or showing notifications. For these type of application specified purpose you can create custom Hooks in React. So basically, Hooks are the functions using in the React to do a particular task.

Creating a Custom Hook

As mentioned earlier custom hook is simple JavaScript function whose name start with use and can call other hooks.In the below example you can see a custom Hook useFetch used to call an API to populate data from the backend.

useFetch.js
// custom hook
const useFetch = () => {

  const sendRequest = async (requestConfig) => {
    try {
        const apiResponse = await fetch(requestConfig.url, {
            method: requestConfig.method ? requestConfig.method : "GET",
            headers: requestConfig.headers ? requestConfig.headers : {},
            body: requestConfig.body ? requestConfig.body : null,
        });

        if (!apiResponse.ok) {
            return {
                data: null,
                error: `An error has occured: ${apiResponse.status}`
            };
        } else {
            const photos = await apiResponse.json();
            return {
                data: photos,
                error: null
            };
      }
    } catch (error) {
      return {
        data: null,
        error: error.message
      };
    }
  };

  return {
    sendRequest
  };
};

export default useFetch;

Using a Custom Hook

Here we are using the above custom hook in the below component to fetch the data.

PhotosHome.js
import { useEffect, useState } from 'react';
import {apiKey} from '../configs/config.env';
import useFetch from '../hooks/useFetch';
import SearchPhotos from './SearchPhotos';

export default function PhotosHome() {

    const [photos, setPhotos] = useState([]);
    const [error, setError] = useState('');
    const { sendRequest } = useFetch();

    // Function to load photos intially
    async function fetchPhotos(){
        const {data, error } = await sendRequest({url: `/photos/?client_id=${apiKey}`});
        setPhotos(data);
        setError(error);
    };

    useEffect(()=>{
        fetchPhotos();
    },[])

    // Function to search photos
    async function searchPhotos(searchQuery){
        const {data, error } = await sendRequest({url: `/search/photos/?client_id=${apiKey}&query=${searchQuery}`});
        setPhotos(data.results);
        setError(error);
    };
    

    return (
        <>
        <SearchPhotos searchPhotos={searchPhotos}/>
        <br/>
            {
             error === null ? 
                photos.map((photo) => {
                    return <img key={photo.id} src={photo.urls.small}></img>
                })
                :
                <p>{error}</p>
            }
        </>
    )
}

Things to remember

  • Custom hooks let share you logic between components.
  • Custom hook only share stateful logic, not the state itself.
  • Custom hook must be named starting with use and followed by a capital letter.
  • Custom hooks should be pure functions.
  • All custom hooks will re-render when your component re-renders.

Benefits of Custom Hooks

  • Reusability
    By using a custom Hook in the component you can avoid the repetitive logic. As in the example shown above, you can use a custom hook to fetch data from backend, and use the same in various places.

  • Encapsulation
    You can hide the complex implementation logics in custom hooks and provide a simple API for consuming by the components.

  • Clean Code
    By abstracting complex and repetitive logics to custom hooks makes your code cleaner and more readable. This seperation allows you to focus on the functionality and make your components more focused on rendering the UI.

Summary

Custom hook is a JavaScript function and It must be named starting with use followed by a capital letter. They are powerful way to encapsulate and reuse logic while giving the benefits sunc as clean code, more readability and flexibility.


Read More