Well you can build your entire application without custom hooks also, then why do we need it.
We need custom hook because –
- Code re-usability
- Code modularity
- Clean and organized code
- Preventing logic repetition i.e. following DRY principal
I know some of the above word might sound jargon to you , so let understand custom hook practically –
Creating a simple online offline notifier
Let’s say I have 2 component , A and B , and I want to check the online offline status in both the component. Its pretty obvious that I have to write same logic in both the components to check the status , so to prevent logic repetition ,I am gonna create one js file , where I will be writing logic and using it in both the components.
Simple. Now lets code .
useOnline.js
import React, { useEffect, useState } from "react";
const useOnline = () => {
const [isOnline, setIsOnline] = useState(true);
console.log("custom hook");
useEffect(() => {
window.addEventListener("online", () => setIsOnline(true));
window.addEventListener("offline", () => setIsOnline(false));
}, []);
return isOnline;
};
export default useOnline;
A.jsx
import useOnline from "../utils/useOnline";
const A = () => {
var isOnline = useOnline();
return loading ? (
<h2>Loading..</h2>
) : (
<div>
<h2>{isOnline ? "🟢Online" : "🔴Offline"}</h2>
</div>
);
};
export default A;

And its done. You have created a custom hook , that checks online offline status.
Watch Video Instead
Create a hook to fetch api and return response
useFetch.js
This custom hooks take api url (get request) , fetch the response and returns data , loading status and the error.
Now while using in actually component, you can either extract all the 3 things or any one or two, its completely upto you.
import { useEffect, useState } from "react";
const useFetch = (url) => {
const [data, setData] = useState();
const [loading, setLoading] = useState(false);
async function getData() {
setLoading(true);
const response = await fetch(url);
const result = await response.json();
setData(result);
setLoading(false);
}
useEffect(() => {
getData();
}, []);
return { data, loading };
};
export default useFetch;
A.jsx (fetching github user data)
import useFetch from "../utils/useFetch";
const A = () => {
const { data, loading } = useFetch("https://api.github.com/users");
return loading ? (
<h2>Loading..</h2>
) : (
<div>
<h2>Github Users</h2>
{data?.map((ele) => (
<li key={ele.id}>{ele.login}</li>
))}
</div>
);
};
export default A;
B.jsx (Fetch fake json data)
import useFetch from "../utils/useFetch";
const B = () => {
const { data, loading } = useFetch(
"https://jsonplaceholder.typicode.com/todos"
);
return loading ? (
<h2>Loading...</h2>
) : (
<div>
<h2>Fake json user</h2>
{data?.map((ele) => (
<li key={ele.id}>{ele.title}</li>
))}
</div>
);
};
export default B;
App.jsx
import { useState } from "react";
import reactLogo from "./assets/react.svg";
import viteLogo from "/vite.svg";
import "./App.css";
import A from "./components/A";
import B from "./components/B";
function App() {
const [count, setCount] = useState(0);
return (
<>
<A />
<B />
</>
);
}
export default App;
Conclusion
While building bigger application , its must to use custom hooks, since it not only make your application clean and readable, it prevents logic repetition, code optimization , hence making the job of developer easy.
Hence, start building custom hook from today
Thank you for ready.
Happy Learning!