A Custom Hook is a JavaScript function whose name starts with "use" and that can call other React hooks. Custom hooks enable developers to extract component state logic into reusable, testable functions shared across multiple components.
flowchart TD
CompA["Component A"] --> CustomHook["useFetch('/api/data')"]
CompB["Component B"] --> CustomHook
CustomHook --> ReactHooks["Encapsulated useState + useEffect"]
useFetch Custom Hookimport { useState, useEffect } from 'react';
// Reusable Custom Hook for HTTP Data Fetching
export function useFetch(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
let isMounted = true;
setLoading(true);
fetch(url)
.then((res) => {
if (!res.ok) throw new Error(`HTTP Error status: ${res.status}`);
return res.json();
})
.then((json) => {
if (isMounted) setData(json);
})
.catch((err) => {
if (isMounted) setError(err.message);
})
.finally(() => {
if (isMounted) setLoading(false);
});
return () => {
isMounted = false;
};
}, [url]);
return { data, loading, error };
}
useLocalStorage Custom Hookimport { useState, useEffect } from 'react';
export function useLocalStorage(key, initialValue) {
const [storedValue, setStoredValue] = useState(() => {
try {
const item = window.localStorage.getItem(key);
return item ? JSON.parse(item) : initialValue;
} catch (error) {
return initialValue;
}
});
useEffect(() => {
try {
window.localStorage.setItem(key, JSON.stringify(storedValue));
} catch (error) {
console.error('LocalStorage write error:', error);
}
}, [key, storedValue]);
return [storedValue, setStoredValue];
}
import React from 'react';
import { useFetch } from './useFetch';
import { useLocalStorage } from './useLocalStorage';
export default function UserDashboard() {
const { data: users, loading, error } = useFetch('https://jsonplaceholder.typicode.com/users');
const [savedTheme, setSavedTheme] = useLocalStorage('preferred_theme', 'dark');
if (loading) return <p>Loading remote users...</p>;
if (error) return <p>Error loading data: {error}</p>;
return (
<div>
<h2>User Count: {users?.length}</h2>
<button onClick={() => setSavedTheme(savedTheme === 'dark' ? 'light' : 'dark')}>
Theme: {savedTheme}
</button>
</div>
);
}
"use": React lint rules rely on the "use" prefix to automatically enforce the Rules of Hooks on custom functions.useFetch inside two different components does NOT share state between them; each component call creates an isolated state instance.Create a custom hook useWindowSize() that returns { width, height } and updates on browser window resize events.
Sign in to track your learning journey, earn industry-recognized certificates, and join our elite developer community.
Quick Access With