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.
Use the share button below if you liked it.
It makes me smile, when I see it.