A custom hook in React is a JavaScript function that leverages React’s built-in hooks—like useState
, useEffect
, useReducer
, etc.—to encapsulate and reuse logic across multiple components. Without custom hooks, you’re just asking for messy, duplicated code everywhere. By extracting shared logic into reusable functions, you can make your components cleaner, more organized, and laser-focused on what they’re actually supposed to do. If you’re not using custom hooks, you’re making your life harder than it needs to be.
If you’re creating a custom hook, it must start with “use”—no exceptions. This isn’t just a suggestion, it’s a rule. React uses this naming convention to treat your function like a hook, ensuring it follows the same strict rules as built-in hooks. That means it gets called in the same order every time the component renders. Ignore this, and you’ll end up with chaos. Stick to the rules, and React will do its job properly.
Knowing how to use a custom hook doesn’t mean you should be using one. Don’t fall into the trap of overusing them. You should only create a custom hook when it’s absolutely necessary—when you find yourself facing these scenarios:
Let’s see examples of custom hooks that you can build:
useLocalStorage
HookLet’s create a custom hook that interacts with the browser’s localStorage
. This hook will allow us to read and write data from localStorage
easily.
import { useState } from 'react';
// Custom Hook to interact with localStorage
function useLocalStorage(key, initialValue) {
// Get stored value or fallback to initial value
const storedValue = localStorage.getItem(key);
// State to hold the value
const [value, setValue] = useState(storedValue ? JSON.parse(storedValue) : initialValue);
// Update localStorage and state
const setStoredValue = (newValue) => {
setValue(newValue);
localStorage.setItem(key, JSON.stringify(newValue));
};
return [value, setStoredValue];
}
export default useLocalStorage;
Here’s a breakdown of how this works:
useState
is used to hold the state of the value, either from localStorage
or the initial value passed to the hook.setStoredValue
function is called, it updates both the React state and the localStorage
at the same time, keeping them in sync.setStoredValue
) that allows components to update that value.Now, you can use this custom hook in your components like this:
import React from 'react';
import useLocalStorage from './useLocalStorage';
function App() {
const [name, setName] = useLocalStorage('name', 'John Doe');
return (
<div>
<h1>Hello, {name}!</h1>
<button onClick={() => setName('Jane Doe')}>Change Name</button>
</div>
);
}
export default App;
useFetch
Hook for Data FetchingHere’s another example—a useFetch
hook that abstracts the logic for fetching data from an API.
import { useState, useEffect } from 'react';
function useFetch(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
const fetchData = async () => {
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error('Failed to fetch');
}
const result = await response.json();
setData(result);
} catch (error) {
setError(error.message);
} finally {
setLoading(false);
}
};
fetchData();
}, [url]);
return { data, loading, error };
}
export default useFetch;
You can use this useFetch
hook in your components to simplify data fetching:
import React from 'react';
import useFetch from './useFetch';
function App() {
const { data, loading, error } = useFetch('https://jsonplaceholder.typicode.com/posts');
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error}</div>;
return (
<div>
<h1>Fetched Posts</h1>
<ul>
{data.map((post) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
</div>
);
}
export default App;
useState
, useEffect
, useContext
, etc., to manage state and side effects.use
to follow React’s conventions. This helps with readability and makes it clear that the function is a hook.Custom hooks are a powerful feature of React that can make your components cleaner, more reusable, and easier to maintain. By encapsulating logic into custom hooks, you can improve the modularity of your code, reduce duplication, and keep your components focused on rendering UI. Whether you’re dealing with complex state, side effects, or external APIs, custom hooks give you the flexibility to build more scalable and maintainable React applications.
If you've played Fortnite, watched a live ESPN match, or used Slack or Microsoft Teams,…
The South Korean government announced on Monday that it had temporarily halted new downloads of…
As a software developer, choosing the right programming language for software development can be a…
A server farm, also known as a server cluster or data center, is a collection…
Pakistan's mobile and broadband internet speeds rank in the bottom 10 percent globally, according to…
React Native is a popular framework for building cross-platform mobile applications using JavaScript and React.…