Refactoring with a Custom Hook
Refactoring a complex component is crucial for maintainability and scalability. In this tutorial, we'll refactor the UsersTable component, extracting business logic into a custom hook for better organization and efficiency.
Original UsersTable Component
The UsersTable displays programmer data, including IDs, names, roles, and working hours. It combines data fetching, processing (like calculating total working hours), and UI rendering.
import React, { useState, useEffect, FunctionComponent } from "react";
import type { Role, User } from "@/types";
export const UsersTable: FunctionComponent = () => {
const [users, setUsers] = useState<User[]>([]);
const [filteredUsers, setFilteredUsers] = useState<User[]>([]);
useEffect(() => {
const fetchUsers = async () => {
const response = await fetch("/api/users");
const data = await response.json();
setUsers(data);
};
fetchUsers();
}, []);
const filterByRole = (role: Role) => {
setFilteredUsers(users.filter(user => user.role === role));
};
// Total working hours calculation
const totalWorkingHours = users.reduce(
(total, user) => total + user.workingHours,
0
);
return <table>{/* Rendering the table */}</table>;
};
Refactoring Step 1: Creating the useUsersTable Custom Hook
import { useState, useEffect } from "react";
export const useUsersTable = () => {
const [users, setUsers] = useState<User[]>([]);
const [filteredUsers, setFilteredUsers] = useState<User[]>([]);
useEffect(() => {
const fetchUsers = async () => {
const response = await fetch("/api/users");
const data = await response.json();
setUsers(data);
};
fetchUsers();
}, []);
const calculateTotalWorkingHours = (): number => {
return users.reduce((total, user) => total + user.workingHours, 0);
};
const filterByRole = (role: Role) => {
setFilteredUsers(users.filter(user => user.role === role));
};
return { calculateTotalWorkingHours, filterByRole, filteredUsers };
};
Refactoring Step 2: Update UsersTable component
The custom hook simplifies UsersTable, making it more maintainable and flexible for future feature additions.
import React, { FunctionComponent } from "react";
import useUsersTable from "./useUsersTable";
const UsersTable: FunctionComponent = () => {
const { filteredUsers, calculateTotalWorkingHours, filterByRole } =
useUsersTable();
return <table>{/* Rendering the table with programmers' data */}</table>;
};
Conclusion
Refactoring with custom hooks in React is a powerful strategy for managing complex components. This approach enhances organization, maintainability, and scalability, especially in large-scale applications. Ensure all functionalities are thoroughly tested.