In ReactJS, hooks, context, services, and functions each have specific roles and are used in different scenarios. Here’s a detailed comparison and a standard file folder structure to help organize your React project:
Hooks
- Purpose: Hooks are functions that let you use state and other React features in functional components. They are designed to encapsulate logic and stateful behavior in functional components.
- Usage: Manage local component state, side effects, context consumption, etc.
- Examples: useState, useEffect, useContext, useReducer, etc.
import React, { useState } from 'react';
const Counter: React.FC = () => {
const [count, setCount] = useState(0);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
};
Context
- Purpose: Context provides a way to share values (such as authentication state or theme) between components without passing props explicitly at every level.
- Usage: Pass data or functions to deeply nested components.
- Components: Context Provider and Context Consumer.
import React, { createContext, useContext, useState } from 'react';
interface AuthContextProps {
user: string | null;
login: (username: string) => void;
logout: () => void;
}
const AuthContext = createContext<AuthContextProps | undefined>(undefined);
export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
const [user, setUser] = useState<string | null>(null);
const login = (username: string) => setUser(username);
const logout = () => setUser(null);
return (
<AuthContext.Provider value={{ user, login, logout }}>
{children}
</AuthContext.Provider>
);
};
export const useAuth = () => {
const context = useContext(AuthContext);
if (!context) {
throw new Error('useAuth must be used within an AuthProvider');
}
return context;
};
Services
- Purpose: Services encapsulate business logic, API interactions, and data processing. They help separate concerns by keeping components focused on UI rendering.
- Usage: Manage complex logic, data fetching, and external interactions.
import { auth } from './firebase'; // Firebase config
import { signInWithEmailAndPassword, signOut } from 'firebase/auth';
export const login = async (email: string, password: string) => {
try {
await signInWithEmailAndPassword(auth, email, password);
console.log('User logged in successfully');
} catch (error) {
console.error('Login error:', error);
}
};
export const logout = async () => {
try {
await signOut(auth);
console.log('User signed out successfully');
} catch (error) {
console.error('Sign-out error:', error);
}
};
Functions
- Purpose: Functions are general-purpose pieces of code that perform specific tasks. In React, they can be used for various purposes, including handlers, utilities, or calculations.
- Usage: Perform tasks or operations that are not necessarily tied to React’s state or lifecycle.
// utils.ts
export const formatDate = (date: Date): string => {
return date.toLocaleDateString();
};
Standard File Folder Structure
A typical React project structure might look like this:
src/
├── assets/ # Static files like images, fonts, etc.
├── components/ # Reusable components
│ ├── Button.tsx
│ └── Header.tsx
├── context/ # Context Providers and Hooks
│ └── AuthContext.tsx
├── hooks/ # Custom hooks
│ └── useAuth.ts
├── services/ # Business logic, API services
│ └── authService.ts
├── pages/ # Page components
│ └── HomePage.tsx
├── utils/ # Utility functions
│ └── formatDate.ts
├── App.tsx # Main app component
├── index.tsx # Entry point of the app
└── styles/ # CSS or styling files
└── main.css
Summary
- Hooks: Manage state and side effects within functional components.
- Context: Share data or functions across the component tree without prop drilling.
- Services: Encapsulate business logic and data interactions, keeping components focused on UI.
- Functions: Perform specific tasks or operations, often used as utilities.