0% completed
Custom hooks are JavaScript functions that allow you to reuse stateful logic across components. They begin with the prefix use (e.g., useFetch, useAuth), which is a convention established by React to distinguish hooks from regular functions.
This prefix also indicates that these functions follow the rules of hooks, such as only being called at the top level of a component or another hook.
The key idea is that custom hooks allow you to encapsulate logic that can be reused across multiple components. These hooks can utilize other React hooks, such as useState or useEffect, to manage state, handle side effects, or interact with component lifecycle events.
Why Use Custom Hooks?
Here are some common scenarios where custom hooks are perfect for:
How to Create a Custom Hook
Let’s walk through building a custom hook with a simple example. Suppose you want to track the current window width and respond to changes.
Step 1: Define the Hook
Create a new file, say useWindowWidth.js
, and define your custom hook.
import { useState, useEffect } from "react"; function useWindowWidth() { const [windowWidth, setWindowWidth] = useState(window.innerWidth); useEffect(() => { const handleResize = () => setWindowWidth(window.innerWidth); // Add event listener when the component mounts window.addEventListener("resize", handleResize); // Cleanup the event listener when the component unmounts return () => window.removeEventListener("resize", handleResize); }, []); return windowWidth; } export default useWindowWidth;
Step 2: Use the Hook in a Component
Now, you can use this hook in any component to access the current window width.
import React from "react"; import useWindowWidth from "./useWindowWidth"; function ResponsiveComponent() { const windowWidth = useWindowWidth(); return ( <div> <h1>Current Window Width: {windowWidth}px</h1> {windowWidth > 768 ? ( <p>You’re using a large screen!</p> ) : ( <p>You’re using a small screen!</p> )} </div> ); } export default ResponsiveComponent;
To use the functionality of the useWindowWidth
function, all you need to do is:
Key Principles for Custom Hooks
Start with use: Always prefix custom hooks with use
word. This is not just a naming convention; it ensures React can identify them as hooks, enabling features like the Rules of Hooks.
Follow the Rules of Hooks: Custom hooks must adhere to the same rules as built-in hooks:
Return Values: Custom hooks can return any value: a state, a function, an object, or a combination.
Example Two: Fetching Data with a Custom Hook
Let’s create another custom hook to handle API calls.
Step 1: Define the Hook
Create a new file, say useFetch.js
, and define your custom hook.
import { useState, useEffect } from "react"; function useFetch(url) { const [data, setData] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { let isMounted = true; const fetchData = async () => { setLoading(true); try { const response = await fetch(url); if (!response.ok) { throw new Error(`Error: ${response.statusText}`); } const result = await response.json(); if (isMounted) { setData(result); } } catch (err) { if (isMounted) { setError(err.message); } } finally { if (isMounted) { setLoading(false); } } }; fetchData(); return () => { isMounted = false; }; }, [url]); return { data, loading, error }; } export default useFetch;
Step 2: Use the Hook in a Component
Now, you can use this hook in any component to fetch data from an API. All you need to do is to insert the url where you want to fetch data from.
import React from "react"; import useFetch from "./useFetch"; function UserList() { const { data, loading, error } = useFetch("https://jsonplaceholder.typicode.com/users"); if (loading) return <p>Loading...</p>; if (error) return <p>Error: {error}</p>; return ( <ul> {data.map((user) => ( <li key={user.id}>{user.name}</li> ))} </ul> ); } export default UserList;
Benefits of Custom Hooks
Common Use Cases for Custom Hooks
Custom hooks are commonly useful for certain tasks such as:
Tips for Creating Effective Custom Hooks
.....
.....
.....