Reusing Logic in React with Custom Hooks: a Practical guide
Kada Guetouache
Posted on August 16, 2024
Custom hooks are a powerful feature in React that are used for more specific purposes unlike React build-in hooks, and it's done by encapsulating common functionalities into independent functions. custom hooks promote re-usability, improve component organization and overall enhance code maintainability.
In this guide will dive into the purposes of using a custom hooks, understanding the fundamental of creating custom hook and how to use it other components. then we will illustrate a real world example by building a fetch API custom hook.
Understanding the basics
usually developer get scared of term custom hooks so lets demystify it.
a custom hooks is simply a function that start with the use
prefix (which is crucial for the custom hooks to work).
this function consist of reusable logic that utilize React build-in hooks. usually you consider using a custom hook if you have same logic across multiple component so by utilizing custom hooks you can solve multiple issues like enhance code organization and maintainability.
Creating a simple custom hook
The example below is a simple counter custom hook that manages the count state using useState
hook and update the count respectively using increment or decrement functions that only set the count state.
import { useState } from 'react'
const useCount = () => {
const [count, setCount] = useState(0)
const increment = () => setCount(prev => prev + 1)
const decrement = () => setCount(prev => prev - 1)
return { count, increment, decrement }
}
export default useCount;
congrats you just build your very own custom hooks it's pretty simple. next will dive into how to use this hook
Using custom hooks in components
using custom hooks in another components is simply done by destruction the returned values form the custom hook inside other components
import useCount from 'customHooks'
const Page = () => {
const {count, increment, decrement} = useCount()
return(
<div>{ count }</div>
<button onClick={increment}> + </button>
<button onClick={decrement}> - </button>
)
}
export default Page
Real world example of using custom hook
one of the most repetitive logic is fetching an API an e-commerce site will fetch data for authentication, payment process, displaying all the products, comments, reviews ... etc.
you can imagine the amount of repetitive fetching logic across the application which can be simplified using a custom hook.
in this section will create a custom fetching hook.
we will be using useState
and useEffect
build-in React hooks
we are gonna have a state for data, a state of pending in case we want to show a spinner while the data is fetching and error state in case of fetch failure.
the code below is self explanatory. inside useEffect
we define a fetchData
function that is asynchronous and that will handle the fetching logic. below the useEffect
the custom hook will return the following values which can be used in all other components data, pending, error
.
notice that we are passing a url value to useFetch custom hook paramater which means that data can be passed to custom hooks
import {useState, useEffect} from 'react'
const useFetch = (url: string) => {
const [data, setData] = useState<any>([])
const [pending, setPending] = useState(false)
const [error, setError] = useState(null)
useEffect(() => {
const fetchData = async () => {
setPending(true)
await fetch(url)
.then(result => {
if (!result.ok) throw new Error('something went wrong!')
return result.json()
})
.then(result => {
setData(result)
setPending(false)
})
.catch(error => setError(error))
}
fetchData()
}, [url])
return { data, pending, error }
}
export default useFetch
by using the useFetch
hook inside Page
components we can now display message to client in case of error, show a spinner while the data is fetching and finally display data to client.
this component can be used repeatedly across all the application which decreases the amount of repetitive code.
import useFetch from './hooks/useFetch'
import Spinner from "./icons/Spinner"
const Page = () => {
const {data, pending, error} = useFetch('https://jsonplaceholder.typicode.com/posts')
if(error) <div>Cloud not fetch data from the server</div>
return(
{pending ?
( <Spinner />)
:
(
data.map((item) => (
<div>
<h3>{item.title}</h3>
<p>{item.body}</div>
</div>
)
)
)}
)
}
export default Page;
Conclusion
Custom hooks offer a powerful mechanism for encapsulating and reusing logic within React components, By extracting common functionalities into a dedicated functions, you can enhance code organization, improve maintainability, and promote code re-usability.
We have explored the fundamentals of creating custom hooks, understanding how to use them within React components and show a real world example of using a custom hook.
Posted on August 16, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.