# React Development Guide for Lin Project
## Overview
This guide documents the React development patterns, best practices, and conventions used in the Lin project. It serves as a reference for current and future developers working on the frontend.
## Project Structure
The frontend follows a component-based architecture with clear separation of concerns:
```
frontend/
├── src/
│ ├── components/ # Reusable UI components
│ │ ├── Header/ # Header component
│ │ ├── Sidebar/ # Sidebar navigation
│ │ └── ... # Other reusable components
│ ├── pages/ # Page-level components
│ ├── services/ # API service layer
│ ├── store/ # Redux store configuration
│ ├── App.jsx # Root component
│ └── index.jsx # Entry point
├── public/ # Static assets
└── package.json # Dependencies and scripts
```
## Core Technologies
- React 18+ with Hooks
- React Router v6 for routing
- Redux Toolkit for state management
- Axios for HTTP requests
- Tailwind CSS for styling
- Material Icons for icons
## Component Development Patterns
### Functional Components with Hooks
All components are implemented as functional components using React hooks:
```jsx
import React, { useState, useEffect } from 'react';
const MyComponent = ({ prop1, prop2 }) => {
const [state, setState] = useState(initialValue);
useEffect(() => {
// Side effects
}, [dependencies]);
return (
{/* JSX */}
);
};
export default MyComponent;
```
### Component Structure
1. **Imports** - All necessary imports at the top
2. **Component Definition** - Functional component with destructured props
3. **State Management** - useState, useEffect, and custom hooks
4. **Helper Functions** - Small utility functions within the component
5. **JSX Return** - Clean, semantic HTML with Tailwind classes
6. **Export** - Default export of the component
### State Management
#### Local Component State
Use `useState` for local component state:
```jsx
const [isOpen, setIsOpen] = useState(false);
const [data, setData] = useState([]);
const [loading, setLoading] = useState(false);
```
#### Global State (Redux)
Use Redux Toolkit for global state management. Structure slices by feature:
```jsx
// store/reducers/featureSlice.js
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
export const fetchFeatureData = createAsyncThunk(
'feature/fetchData',
async (params) => {
const response = await api.getFeatureData(params);
return response.data;
}
);
const featureSlice = createSlice({
name: 'feature',
initialState: {
items: [],
loading: false,
error: null
},
reducers: {
clearError: (state) => {
state.error = null;
}
},
extraReducers: (builder) => {
builder
.addCase(fetchFeatureData.pending, (state) => {
state.loading = true;
})
.addCase(fetchFeatureData.fulfilled, (state, action) => {
state.loading = false;
state.items = action.payload;
})
.addCase(fetchFeatureData.rejected, (state, action) => {
state.loading = false;
state.error = action.error.message;
});
}
});
export const { clearError } = featureSlice.actions;
export default featureSlice.reducer;
```
### Props and Prop Types
Destructure props in the component signature and provide default values when appropriate:
```jsx
const MyComponent = ({
title,
items = [],
isLoading = false,
onAction = () => {}
}) => {
// Component implementation
};
```
### Event Handling
Use inline arrow functions or separate handler functions:
```jsx
// Inline
// Separate function
const handleDelete = (id) => {
dispatch(deleteItem(id));
};
```
## Styling with Tailwind CSS
The project uses Tailwind CSS for styling. Follow these conventions:
### Class Organization
1. **Layout classes** (flex, grid, etc.) first
2. **Positioning** (relative, absolute, etc.)
3. **Sizing** (w-, h-, etc.)
4. **Spacing** (m-, p-, etc.)
5. **Typography** (text-, font-, etc.)
6. **Visual** (bg-, border-, shadow-, etc.)
7. **Interactive states** (hover:, focus:, etc.)
```jsx
{/* Content */}
```
### Responsive Design
Use Tailwind's responsive prefixes (sm:, md:, lg:, xl:) for responsive styles:
```jsx
{/* Content */}
{/* Content */}
```
### Custom Classes
For complex components, use component-specific classes in conjunction with Tailwind:
```jsx
`
nav-link group relative flex items-center px-3 py-2.5 text-sm font-medium rounded-lg
transition-all duration-200 ease-in-out
${isActive
? 'bg-gradient-to-r from-primary-600 to-primary-700 text-white'
: 'text-secondary-700 hover:bg-accent-100'
}
`}
>
```
## Routing
Use React Router v6 for navigation:
```jsx
import { Routes, Route, useNavigate, useLocation } from 'react-router-dom';
// In App.jsx
} />
} />
} />
} />
// In components
const navigate = useNavigate();
const location = useLocation();
// Navigation
navigate('/dashboard');
// Check current route
if (location.pathname === '/dashboard') {
// Do something
}
```
## API Integration
### Service Layer
Create service functions for API calls:
```jsx
// services/api.js
import axios from 'axios';
const API_BASE_URL = process.env.REACT_APP_API_URL || 'http://localhost:5000';
const api = axios.create({
baseURL: API_BASE_URL,
timeout: 10000,
});
// Request interceptor
api.interceptors.request.use((config) => {
const token = localStorage.getItem('token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
});
// Response interceptor
api.interceptors.response.use(
(response) => response,
(error) => {
if (error.response?.status === 401) {
// Handle unauthorized access
localStorage.removeItem('token');
window.location.href = '/login';
}
return Promise.reject(error);
}
);
export default api;
// services/featureService.js
import api from './api';
export const getFeatures = async () => {
const response = await api.get('/api/features');
return response.data;
};
export const createFeature = async (data) => {
const response = await api.post('/api/features', data);
return response.data;
};
```
### Async Operations with Redux Thunks
Use createAsyncThunk for asynchronous operations:
```jsx
// In slice
export const fetchData = createAsyncThunk(
'feature/fetchData',
async (_, { rejectWithValue }) => {
try {
const data = await featureService.getFeatures();
return data;
} catch (error) {
return rejectWithValue(error.response.data);
}
}
);
// In component
const dispatch = useDispatch();
const { items, loading, error } = useSelector(state => state.feature);
useEffect(() => {
dispatch(fetchData());
}, [dispatch]);
```
## Accessibility (a11y)
Implement proper accessibility features:
1. **Semantic HTML** - Use appropriate HTML elements
2. **ARIA attributes** - When needed for dynamic content
3. **Keyboard navigation** - Ensure all interactive elements are keyboard accessible
4. **Focus management** - Proper focus handling for modals, dropdowns, etc.
5. **Screen reader support** - Use aria-label, aria-describedby, etc.
```jsx
```
## Performance Optimization
### Memoization
Use React.memo for components that render frequently:
```jsx
const MyComponent = React.memo(({ data, onUpdate }) => {
// Component implementation
});
export default MyComponent;
```
### useCallback and useMemo
Optimize expensive calculations and callback functions:
```jsx
const expensiveValue = useMemo(() => {
return computeExpensiveValue(data);
}, [data]);
const handleClick = useCallback((id) => {
dispatch(action(id));
}, [dispatch]);
```
### Lazy Loading
Use React.lazy for code splitting:
```jsx
import { lazy, Suspense } from 'react';
const LazyComponent = lazy(() => import('./components/MyComponent'));
Loading...}>
```
## Error Handling
### Error Boundaries
Implement error boundaries for catching JavaScript errors:
```jsx
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
return { hasError: true };
}
componentDidCatch(error, errorInfo) {
console.error('Error caught by boundary:', error, errorInfo);
}
render() {
if (this.state.hasError) {
return
)}
```
## Testing
### Unit Testing
Use Jest and React Testing Library for unit tests:
```jsx
import { render, screen, fireEvent } from '@testing-library/react';
import MyComponent from './MyComponent';
test('renders component with title', () => {
render();
expect(screen.getByText('Test Title')).toBeInTheDocument();
});
test('calls onClick when button is clicked', () => {
const handleClick = jest.fn();
render();
fireEvent.click(screen.getByRole('button'));
expect(handleClick).toHaveBeenCalledTimes(1);
});
```
### Redux Testing
Test Redux slices and async thunks:
```jsx
import featureReducer, { fetchData } from './featureSlice';
test('handles fulfilled fetch data', () => {
const initialState = { items: [], loading: false, error: null };
const data = [{ id: 1, name: 'Test' }];
const action = { type: fetchData.fulfilled, payload: data };
const state = featureReducer(initialState, action);
expect(state.items).toEqual(data);
expect(state.loading).toBe(false);
});
```
## Mobile Responsiveness
### Touch Optimization
Add touch-specific classes and handlers:
```jsx
```
### Responsive Breakpoints
Use Tailwind's responsive utilities for different screen sizes:
- Mobile: Default styles (0-767px)
- Tablet: `sm:` (768px+) and `md:` (1024px+)
- Desktop: `lg:` (1280px+) and `xl:` (1536px+)
### Mobile-First Approach
Start with mobile styles and enhance for larger screens:
```jsx
{/* Content that stacks on mobile, side-by-side on desktop */}
```
## Best Practices
### Component Design
1. **Single Responsibility** - Each component should have one clear purpose
2. **Reusability** - Design components to be reusable across the application
3. **Composition** - Build complex UIs by composing simpler components
4. **Controlled Components** - Prefer controlled components for form elements
5. **Props Drilling** - Use context or Redux to avoid excessive prop drilling
### Code Organization
1. **Consistent Naming** - Use consistent naming conventions (PascalCase for components)
2. **Logical Grouping** - Group related files in directories
3. **Export Strategy** - Use default exports for components, named exports for utilities
4. **Import Organization** - Group imports logically (external, internal, styles)
### Performance
1. **Bundle Size** - Monitor bundle size and optimize when necessary
2. **Rendering** - Use React.memo, useMemo, and useCallback appropriately
3. **API Calls** - Implement caching and pagination where appropriate
4. **Images** - Optimize images and use lazy loading
### Security
1. **XSS Prevention** - React automatically escapes content, but be careful with dangerouslySetInnerHTML
2. **Token Storage** - Store JWT tokens securely (HttpOnly cookies or secure localStorage)
3. **Input Validation** - Validate and sanitize user inputs
4. **CORS** - Ensure proper CORS configuration on the backend
This guide should help maintain consistency and quality across the React frontend implementation in the Lin project.