Custom hooks allow you to extract and reuse stateful logic across different components in React. They follow the same principles as built-in hooks, but you create them yourself to handle more complex or reusable logic. Custom hooks should start with the use
prefix to indicate their intended use in function components.
React Custom Hooks
1. Creating a Simple Custom Hook
To create a custom hook, you simply create a JavaScript function that uses React’s built-in hooks (like useState
and useEffect
) and returns data or functions that can be reused across multiple components.
For example, here is a custom hook that manages a counter:
import { useState } from 'react';
// Custom hook to manage a counter
function useCounter(initialValue = 0) {
const [count, setCount] = useState(initialValue);
const increment = () => setCount(count + 1);
const decrement = () => setCount(count - 1);
return { count, increment, decrement };
}
export default useCounter;
This useCounter
hook allows you to manage a counter state and provides two functions to increment and decrement the count. You can now reuse this hook in any component where you need a counter.
2. Using a Custom Hook in a Component
Once you've created a custom hook, you can use it inside any functional component. For example, let's use the useCounter
hook in a component to manage the state of a counter:
import React from 'react';
import useCounter from './useCounter';
function CounterComponent() {
const { count, increment, decrement } = useCounter(0);
return (
<div>
<h1>Count: {count}</h1>
<button onClick={increment}>Increment</button>
<button onClick={decrement}>Decrement</button>
</div>
);
}
export default CounterComponent;
In this example, the useCounter
hook is imported and used inside the CounterComponent
component.
The component has buttons that call the increment
and decrement
functions to modify the count state.
3. Custom Hook with useEffect
You can also use useEffect
inside custom hooks to perform side effects. For example, you can create a custom hook that fetches data when the component mounts:
import { useState, useEffect } from 'react';
// Custom hook for fetching data
function useFetch(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
fetch(url)
.then(response => response.json())
.then(data => {
setData(data);
setLoading(false);
})
.catch(error => {
setError(error);
setLoading(false);
});
}, [url]);
return { data, loading, error };
}
export default useFetch;
This useFetch
hook fetches data from a provided URL and returns the fetched data, loading state, and any errors encountered during the fetch process.
4. Using the Custom useFetch Hook
You can use the useFetch
hook to fetch data in a component as shown below:
import React from 'react';
import useFetch from './useFetch';
function DataFetchingComponent() {
const { data, loading, error } = useFetch('https://jsonplaceholder.typicode.com/posts');
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
return (
<div>
<h1>Fetched Data:</h1>
<ul>
{data.map(item => (
<li key={item.id}>{item.title}</li>
))}
</ul>
</div>
);
}
export default DataFetchingComponent;
In this example, the useFetch
hook is used to fetch data from an API and display the results. It handles loading and error states, providing a clean way to handle fetching logic in a reusable manner.
5. Summary
Custom hooks in React are an excellent way to extract and reuse logic across components. They allow you to encapsulate stateful logic and side effects, making your code more modular and easier to maintain.
By following the pattern of using use
as the prefix, custom hooks make it easier to create reusable pieces of logic that work seamlessly within React’s function components.