Introduction
In this chapter, we will explore how to create custom hooks in React. Custom hooks allow you to encapsulate reusable logic and stateful behavior in a function that can be shared across multiple components. This can help you write cleaner and more maintainable code. We will create a new React project from scratch, explain the syntax of custom hooks, and walk through a real-time project step by step to demonstrate their usage.
Table of Contents
- Setting Up a New React Project
- What are Custom Hooks?
- Creating a Custom Hook
- Project Setup
- Creating a useFetch Hook
- Using useFetch in a Component
- Real-Time Project: Employee Management System with Custom Hooks
- Project Setup
- Creating the useEmployeeData Hook
- Using useEmployeeData in the Employee Component
- Conclusion
Setting Up a New React Project
First, let’s create a new React project using the create-react-app tool.
-
Open your terminal and run the following command:
npx create-react-app custom-hooks-employee-app -
Navigate to the project directory:
cd custom-hooks-employee-app
What are Custom Hooks?
Custom hooks are JavaScript functions that start with the word "use" and can call other hooks. They allow you to extract and reuse logic and stateful behavior in a way that is easy to share across multiple components.
Example
Here’s a simple example of a custom hook that logs a message when a component mounts and unmounts:
import { useEffect } from 'react';
function useLogger(message) {
useEffect(() => {
console.log(message);
return () => {
console.log(`Cleanup: ${message}`);
};
}, [message]);
}
export default useLogger;
You can use this custom hook in any component:
import React from 'react';
import useLogger from './useLogger';
function MyComponent() {
useLogger('MyComponent mounted');
return <div>MyComponent</div>;
}
export default MyComponent;
Creating a Custom Hook
Project Setup
-
Open the project directory in your code editor.
-
Remove the default content from
src/App.jsandsrc/App.css:// src/App.js import React from 'react'; import './App.css'; import Employee from './Employee'; function App() { return ( <div className="App"> <h1>Employee Management System</h1> <Employee /> </div> ); } export default App;/* src/App.css */ .App { text-align: center; padding: 20px; } h1 { margin-bottom: 20px; }
Creating a useFetch Hook
-
Create a new file named
useFetch.jsin thesrcdirectory. -
Define the
useFetchhook:// src/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(() => { 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); setLoading(false); }); }, [url]); return { data, loading, error }; } export default useFetch;Explanation:
- The
useFetchhook takes a URL as an argument and fetches data from that URL. - It returns an object containing
data,loading, anderrorstates.
- The
Using useFetch in a Component
-
Create a new file named
Employee.jsin thesrcdirectory. -
Define the
Employeecomponent:// src/Employee.js import React from 'react'; import useFetch from './useFetch'; import './Employee.css'; function Employee() { const { data: employees, loading, error } = useFetch('https://jsonplaceholder.typicode.com/users'); if (loading) return <p>Loading...</p>; if (error) return <p>Error: {error.message}</p>; return ( <div className="container mt-5"> <ul className="list-group"> {employees.map((employee) => ( <li key={employee.id} className="list-group-item"> {employee.id} - {employee.name} ({employee.email}) </li> ))} </ul> </div> ); } export default Employee;Explanation:
- The
Employeecomponent uses theuseFetchhook to fetch employee data from an API. - It handles the loading and error states and displays the employee data in a list.
- The
-
Create a CSS file named
Employee.cssto style the Employee component:/* src/Employee.css */ .container { max-width: 600px; margin: 0 auto; text-align: left; } .list-group-item { display: flex; justify-content: space-between; align-items: center; padding: 10px; border: 1px solid #ccc; border-radius: 4px; margin-bottom: 10px; }
Real-Time Project: Employee Management System with Custom Hooks
Project Setup
- Ensure the project is set up as previously described.
Creating the useEmployeeData Hook
-
Create a new file named
useEmployeeData.jsin thesrcdirectory. -
Define the
useEmployeeDatahook:// src/useEmployeeData.js import { useState, useEffect } from 'react'; function useEmployeeData(url) { const [employees, setEmployees] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { fetch(url) .then((response) => { if (!response.ok) { throw new Error('Network response was not ok'); } return response.json(); }) .then((data) => { setEmployees(data); setLoading(false); }) .catch((error) => { setError(error); setLoading(false); }); }, [url]); return { employees, loading, error }; } export default useEmployeeData;Explanation:
- The
useEmployeeDatahook takes a URL as an argument and fetches employee data from that URL. - It returns an object containing
employees,loading, anderrorstates.
- The
Using useEmployeeData in the Employee Component
-
Modify the
Employeecomponent to use theuseEmployeeDatahook:// src/Employee.js import React from 'react'; import useEmployeeData from './useEmployeeData'; import './Employee.css'; function Employee() { const { employees, loading, error } = useEmployeeData('https://jsonplaceholder.typicode.com/users'); if (loading) return <p>Loading...</p>; if (error) return <p>Error: {error.message}</p>; return ( <div className="container mt-5"> <ul className="list-group"> {employees.map((employee) => ( <li key={employee.id} className="list-group-item"> {employee.id} - {employee.name} ({employee.email}) </li> ))} </ul> </div> ); } export default Employee;Explanation:
- The
Employeecomponent now uses theuseEmployeeDatahook to fetch employee data. - This makes the component cleaner and more focused on rendering, while the data fetching logic is encapsulated in the custom hook.
- The
Conclusion
In this chapter, we created a new React project and explored custom hooks. We learned what custom hooks are and how to create them. We walked through a real-time project step by step, creating a useFetch hook and a useEmployeeData hook to fetch and manage employee data. By understanding and using custom hooks, you can encapsulate reusable logic and stateful behavior, making your React applications cleaner and more maintainable.