React Custom Hooks

React Custom Hooks

React Custom Hooks allow you to extract reusable logic from components, making your code cleaner and more maintainable. They enable you to encapsulate functionality like fetching data, handling forms, or managing state across multiple components.

Why Use Custom Hooks?

✅ Code Reusability: Avoid duplicate logic in multiple components.
✅ Better Organization: Keeps components focused on UI.
✅ Improved Readability: Encapsulates logic into separate functions.
✅ Stateful Logic Sharing: Allows sharing state logic without relying on higher-order components or render props.

Creating a Custom Hook

A custom hook is simply a JavaScript function that starts with use and can use other hooks inside it.

👉 Example: Creating a useCounter Hook

This custom hook manages a counter with three functions:
•  Increment (+1)
  Decrement (-1)
•  Reset (Back to initial value)

📌 Custom Hook (useCounter.js)

import { useState } from ‘react’;

function useCounter(initialValue = 0) {
const [count, setCount] = useState(initialValue);

const increment = () => setCount((prev) => prev + 1);
const decrement = () => setCount((prev) => prev – 1);
const reset = () => setCount(initialValue);

return { count, increment, decrement, reset };
}

export default useCounter;

👉 Using the useCounter Hook in a Component

We can now use this hook in any component.

📌 Counter Component (CounterComponent.js)

import React from ‘react’;
import useCounter from ‘./useCounter’;

function CounterComponent() {
const { count, increment, decrement, reset } = useCounter(5);

return (
<div>
<h1>Count: {count}</h1>
<button onClick={increment}>Increase</button>
<button onClick={decrement}>Decrease</button>
<button onClick={reset}>Reset</button>
</div>
);
}

export default CounterComponent;

📝 How It Works

✔️ The useCounter(5) hook initializes the count at 5.
✔️ Clicking Increase increments the count.
✔️ Clicking Decrease decrements the count.
✔️ Clicking Reset restores it to 5.

🎯 Advantages of Custom Hooks

✔ Code Reusability – Use the useCounter hook in multiple components.
✔ Separation of Concerns – Keeps logic outside the UI component.
✔ Encapsulation – State management is handled within the hook.

Custom Hook for Fetching Data (useFetch)

Fetching data is a common requirement in React applications. Creating a custom hook for data fetching helps simplify the logic and improves reusability.

👉 Creating the useFetch Hook

This hook:
•  Fetches data from a given URL.
•  Manages loading and error states.
•  Uses useEffect to fetch data when the URL changes.

📌 Custom Hook (useFetch.js)

import { useState, useEffect } from ‘react’;

function useFetch(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);

useEffect(() => {
setLoading(true);
fetch(url)
.then((response) => {
if (!response.ok) {
throw new Error(‘Network response was not ok’);
}
return response.json();
})
.then((data) => {
setData(data);
setLoading(false);
})
.catch((error) => {
setError(error.message);
setLoading(false);
});
}, [url]);

return { data, loading, error };
}

export default useFetch;

👉 Using useFetch in a Component

We can now use the useFetch hook to retrieve data easily.

📌 Example: Fetching a List of Users (UsersList.js)

import React from ‘react’;
import useFetch from ‘./useFetch’;

function UsersList() {
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 UsersList;

📝 How It Works:

✔️ useFetch(‘https://jsonplaceholder.typicode.com/users’) runs when the component mounts.
✔️ If loading, it shows “Loading…”.
✔️ If there’s an error, it displays the error message.
✔️ Once data is fetched, it displays a list of users’ names.

🎯 Advantages of useFetch Custom Hook

✔ Code Reusability – Use the useFetch hook in different components.
✔ Encapsulation – Keeps API logic separate from UI components.
✔ Improved Readability – Makes components cleaner and more readable.

👉 Creating the useLocalStorage Hook

This hook:
•  Retrieves stored data from localStorage.
•  Saves new data into localStorage.
  Ensures data is updated when changed.

📌 Custom Hook (useLocalStorage.js)

import { useState } from ‘react’;

function useLocalStorage(key, initialValue) {
const [storedValue, setStoredValue] = useState(() => {
try {
const item = window.localStorage.getItem(key);
return item ? JSON.parse(item) : initialValue;
} catch (error) {
console.error(“Error accessing localStorage:”, error);
return initialValue;
}
});

const setValue = (value) => {
try {
setStoredValue(value);
window.localStorage.setItem(key, JSON.stringify(value));
} catch (error) {
console.error(“Error saving to localStorage:”, error);
}
};

return [storedValue, setValue];
}

export default useLocalStorage;

👉 Using useLocalStorage in a Component

This component allows users to store their name in local storage.

📌 Example: Storing and Displaying a Name (NameSaver.js)

import React from ‘react’;
import useLocalStorage from ‘./useLocalStorage’;

function NameSaver() {
const [name, setName] = useLocalStorage(‘name’, ”);

return (
<div>
<input
value={name}
onChange={(e) => setName(e.target.value)}
placeholder=”Enter your name”
/>
<p>Stored Name: {name}</p>
</div>
);
}

export default NameSaver;

📝 How It Works

✔️ The useLocalStorage hook fetches the stored value (if any) from localStorage.
✔️ If no value is found, it uses the initialValue provided.
✔️ When the user types a new name, it gets stored in local storage and updates in real-time.
✔️ If the page is refreshed, the name remains stored.

🎯 Advantages of useLocalStorage Custom Hook

✔ Persistent Storage – Data remains even after page refresh.
✔ Reusable Hook – Use useLocalStorage for any data type.
✔ Encapsulated Logic – Keeps components cleaner by handling storage separately.

Best Practices for Custom Hooks

✅ Always start function names with use (e.g., useCounter, useFetch).
✅ Keep hooks focused on a single responsibility.
✅ Return only necessary values and functions from the hook.
✅ Use existing hooks inside custom hooks (useState, useEffect, etc.).
✅ Ensure reusability across different components.

Conclusion

Custom hooks in React improve code reusability, readability, and state management. By encapsulating logic into separate functions, you keep components clean and maintainable. Learning to create and use custom hooks can significantly enhance your React development skills!

Course Video in English