Custom Hook in React | Step By Step Guide

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

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
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;
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;
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

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
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;
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;
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.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
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;
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;
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)

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
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;
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;
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)

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
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;
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;
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

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
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;
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;
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!

Help Others

Leave a Reply

Your email address will not be published. Required fields are marked *