A custom hook is a JavaScript function that starts with use and internally calls other hooks like useState, useEffect, or useContext. It allows developers to extract reusable logic, keeping components clean and modular.
Syntax
function useCustomHook() {
// Use built-in hooks here
return someValue;
}Steps to Create a Custom Hook
1. Define a Function That Starts with use
Custom hooks must follow React's naming convention and start with use (e.g., useFetch). This ensures React recognizes it as a hook and enforces hook rules.
function useCustomHook() {
// Hook logic here
return someValue;
}2. Use React's Built-in Hooks Inside Your Custom Hook
Custom hooks can use useState, useEffect, useContext, etc., to manage state, handle side effects, or access context.
function useCounter() {
const [count, setCount] = useState(0);
return [count, () => setCount(count + 1)];
}3. Add Logic Inside useEffect for Side Effects
If your custom hook performs side effects (e.g., fetching data, subscribing to a service), use useEffect to control when the effect runs.
function useFetchData(url) {
const [data, setData] = useState(null);
useEffect(() => {
fetch(url).then(response => response.json()).then(setData);
}, [url]);
return data;
}4. Return Necessary Values
Your custom hook should return state, functions, or values that components need, such as fetched data, loading state, or error messages.
function useToggle(initialValue = false) {
const [state, setState] = useState(initialValue);
const toggle = () => setState(prev => !prev);
return [state, toggle];
}5. Use the Custom Hook in Components
Once defined, your custom hook can be used inside a React component just like a built-in hook.
function ExampleComponent() {
const [isOn, toggle] = useToggle();
return <button onClick={toggle}>{isOn ? "ON" : "OFF"}</button>;
}Implementing A Custom Hook
1. Creating a Custom Hook for Fetching Data
Custom hooks can be used for handling the API requests.
JavaScript
import { useState, useEffect } from 'react';
function useFetch(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetch(url)
.then((response) => response.json())
.then((data) => {
setData(data);
setLoading(false);
});
}, [url]);
return { data, loading };
}
function DataComponent() {
const { data, loading } = useFetch("https://jsonplaceholder.typicode.com/todos/1");
return (
<div>
{loading ? <p>Loading...</p> : <p>Data: {JSON.stringify(data)}</p>}
</div>
);
}
export default DataComponent;
Output
Creating a Custom Hook for Fetching DataIn this example
- useFetch is the custom hook.
- useFetch encapsulates API-fetching logic, making it reusable.
- Components using useFetch don't have to implement fetching logic themselves.
This example consists of a custom hook (useOnlineStatus) that tracks the online/offline status of a user and a React component (SaveButton) that uses this custom hook to enable or disable a button based on the network status.
JavaScript
//src/App.js
import useOnlineStatus from './useOnlineStatus';
export default function SaveButton() {
const isOnline = useOnlineStatus();
function handleSaveClick() {
console.log('✅ Progress saved');
}
return (
<button disabled={!isOnline} onClick={handleSaveClick}>
{isOnline ? 'Save progress' : 'Reconnecting...'}
</button>
);
}
JavaScript
//src/useOnlineStatus.js
import { useState, useEffect } from 'react';
function useOnlineStatus() {
const [isOnline, setIsOnline] = useState(navigator.onLine);
useEffect(() => {
function handleOnline() {
setIsOnline(true);
}
function handleOffline() {
setIsOnline(false);
}
window.addEventListener('online', handleOnline);
window.addEventListener('offline', handleOffline);
return () => {
window.removeEventListener('online', handleOnline);
window.removeEventListener('offline', handleOffline);
};
}, []);
return isOnline;
}
export default useOnlineStatus;
Output
In this example
- useOnlineStatus hook tracks the user's internet connection status using useState and useEffect. It listens for online and offline events and updates the state accordingly.
- This component imports the useOnlineStatus hook to determine whether the user is online. If offline, the button is disabled and displays "Reconnecting...". If online, the button is enabled with "Save progress."
- The useEffect inside the custom hook adds event listeners for network status changes and cleans them up when the component unmounts to prevent memory leaks.
- useOnlineStatus is a custom hook because it encapsulates the logic for checking internet status and can be reused across multiple components.
When to Use Custom Hooks
You should use custom hooks when
- We need to reuse logic across multiple components.
- We want to improve readability and maintainability by keeping component logic clean.
- We are using multiple built-in hooks together in a reusable way.
- We want to encapsulate side effects like data fetching or state management
Which of the following is a required rule when creating a custom hook in React?
-
-
It must start with the prefix "use"
-
It must only use useState
-
It must extend React.Component
Explanation:
React requires custom hooks to start with "use" (e.g., useFetch, useToggle). This allows React to detect hook usage and enforce hook rules.
What is the main advantage of using a custom hook?
-
-
It allows creating reusable logic shared across multiple components
-
It prevents components from re-rendering
-
It replaces the need for useEffect
Explanation:
Custom hooks encapsulate reusable, complex logic so components stay cleaner and more modular.
Which built-in hook is typically used inside a custom hook to manage side effects such as fetching data?
Explanation:
useEffect manages side effects such as fetching data, event listeners, subscriptions, and timers—common logic inside custom hooks.
In the useFetch example, what does the custom hook return?
-
-
-
An object containing data and loading values
-
A function to stop fetching
Explanation:
useFetch returns { data, loading }, allowing components to read fetched data and determine loading state.
Quiz Completed Successfully
Your Score : 2/4
Accuracy : 0%
Login to View Explanation
1/4
1/4
< Previous
Next >
Explore
React Fundamentals
Components in React
React Hooks
Routing in React
Advanced React Concepts
React Projects