1. Code Organization and Structure:
reduxstate-managementperformance-optimizationtesting-strategiescode-structure
Description
This rule provides comprehensive guidance on Redux best practices, covering code structure, performance optimization, testing strategies, and common pitfalls to ensure robust and maintainable Redux applications.
Globs
**/*.{js,jsx,ts,tsx}
---
description: This rule provides comprehensive guidance on Redux best practices, covering code structure, performance optimization, testing strategies, and common pitfalls to ensure robust and maintainable Redux applications.
globs: **/*.{js,jsx,ts,tsx}
---
- **Introduction:** This document outlines best practices for developing applications with Redux, covering various aspects from code organization to performance optimization.
## 1. Code Organization and Structure:
- **Directory Structure:** Organize your Redux-related files in a clear and maintainable structure. A feature-based approach is recommended.
- Example:
src/
├── app/
│ ├── store.js # Redux store configuration
├── features/
│ ├── counter/ # Feature module (e.g., 'counter')
│ │ ├── counterSlice.js # Redux slice (reducers + actions)
│ │ ├── Counter.jsx # React component
│ │ ├── counterAPI.js # API interaction logic
│ │ └── counterSelectors.js # Selectors
│ ├── todos/
│ │ └── ...
├── components/ # Reusable UI components
├── utils/ # Utility functions
└── ...
- **File Naming Conventions:** Use consistent and descriptive names for your files.
- Example:
- `counterSlice.js` for Redux slice files
- `Counter.jsx` for React components
- `counterActions.js` or preferably included in slice
- `counterSelectors.js` for selectors
- **Module Organization:** Group related logic into modules. Each feature should have its own directory containing its Redux slice, components, and selectors.
- **Component Architecture:** Use a container/presentational component pattern to separate data fetching and state management logic from UI rendering.
- **Container Components:** Connect to the Redux store and pass data to presentational components.
- **Presentational Components:** Focus on UI rendering and receive data and callbacks as props.
- **Code Splitting Strategies:** Implement code splitting to reduce the initial bundle size and improve loading times.
- **Route-based splitting:** Load different parts of the application based on the current route.
- **Component-based splitting:** Lazy-load components that are not immediately needed.
- Use `React.lazy` and `<Suspense>` for component-based splitting.
## 2. Common Patterns and Anti-patterns:
- **Design Patterns:**
- **Flux Standard Actions (FSA):** A convention for structuring Redux actions with a `type` and an optional `payload` and `error` property.
- **Selectors:** Use selectors (e.g., with Reselect) to derive data from the Redux store efficiently.
- **Thunks/Sagas:** Manage asynchronous side effects using Redux Thunk or Redux Saga.
- **Recommended Approaches:**
- **Redux Toolkit:** Use Redux Toolkit to simplify Redux development and reduce boilerplate.
- **Immutability:** Treat state as immutable and use immutable data structures or techniques to update it.
- **Normalization:** Normalize your state to reduce data duplication and improve data consistency.
- **Anti-patterns and Code Smells:**
- **Mutating State Directly:** Never mutate state directly. Always create new copies of objects and arrays.
- **Putting too much logic in components:** Keep components focused on rendering. Move complex logic to reducers, selectors, or middleware.
- **Large Reducers:** Split large reducers into smaller, more manageable reducers using `combineReducers`.
- **Over-fetching Data:** Fetch only the data that is needed by the component. Use selectors to derive specific data subsets from the state.
- **State Management Best Practices:**
- **Single Source of Truth:** Keep all application state in the Redux store.
- **Predictable State Updates:** Ensure that state updates are predictable and deterministic.
- **Minimize Global State:** Only store data that is truly global in the Redux store. Local component state should be used for UI-specific data.
- **Error Handling Patterns:**
- **Action-based Error Handling:** Dispatch actions to indicate errors and update the state accordingly.
- **Middleware Error Handling:** Use middleware to catch errors and log them to a central error reporting service.
## 3. Performance Considerations:
- **Optimization Techniques:**
- **Memoization:** Use memoization to avoid unnecessary re-renders. Use `React.memo` for functional components and `shouldComponentUpdate` for class components.
- **Selectors:** Use selectors with memoization (e.g., Reselect) to avoid recomputing derived data when the input state hasn't changed.
- **Batch Updates:** Batch multiple state updates into a single update to reduce the number of re-renders.
- **Debouncing/Throttling:** Use debouncing or throttling to limit the frequency of updates.
- **Memory Management:**
- **Avoid Memory Leaks:** Clean up event listeners and timers when components unmount.
- **Optimize Data Structures:** Use efficient data structures to reduce memory usage.
- **Rendering Optimization:**
- **Virtualization:** Use virtualization for large lists to only render the visible items.
- **Code Splitting:** Reduce the initial bundle size by splitting the code into smaller chunks.
- **Bundle Size Optimization:**
- **Tree Shaking:** Remove unused code from the bundle using tree shaking.
- **Minification:** Minify the code to reduce the bundle size.
- **Compression:** Compress the bundle using Gzip or Brotli.
- **Lazy Loading Strategies:**
- **Route-based Lazy Loading:** Load different routes on demand.
- **Component-based Lazy Loading:** Load components on demand using `React.lazy`.
## 4. Security Best Practices:
- **Common Vulnerabilities:**
- **Cross-Site Scripting (XSS):** Prevent XSS attacks by sanitizing user inputs and escaping outputs.
- **Cross-Site Request Forgery (CSRF):** Protect against CSRF attacks by using anti-CSRF tokens.
- **Data Injection:** Prevent data injection attacks by validating and sanitizing inputs.
- **Input Validation:**
- **Client-Side Validation:** Validate inputs on the client-side to provide immediate feedback to the user.
- **Server-Side Validation:** Validate inputs on the server-side to ensure data integrity.
- **Authentication and Authorization Patterns:**
- **JWT (JSON Web Tokens):** Use JWTs for authentication and authorization.
- **Role-Based Access Control (RBAC):** Implement RBAC to control access to different parts of the application.
- **Data Protection Strategies:**
- **Encryption:** Encrypt sensitive data at rest and in transit.
- **Data Masking:** Mask sensitive data to protect it from unauthorized access.
- **Secure API Communication:**
- **HTTPS:** Use HTTPS to encrypt communication between the client and the server.
- **API Rate Limiting:** Implement API rate limiting to prevent abuse.
## 5. Testing Approaches:
- **Unit Testing Strategies:**
- **Test Reducers:** Test reducers to ensure that they update the state correctly.
- **Test Actions:** Test actions to ensure that they dispatch the correct payloads.
- **Test Selectors:** Test selectors to ensure that they derive the correct data from the state.
- **Integration Testing:**
- **Test Components:** Test components to ensure that they render correctly and interact with the Redux store.
- **Test Middleware:** Test middleware to ensure that they handle side effects correctly.
- **End-to-end Testing:**
- **Test User Flows:** Test user flows to ensure that the application works as expected from the user's perspective.
- **Test Organization:**
- **Test Directory Structure:** Organize tests in a clear and maintainable structure.
- Example:
src/
├── features/
│ ├── counter/
│ │ ├── counterSlice.test.js
│ │ ├── Counter.test.jsx
- **Mocking and Stubbing:**
- **Mock API Calls:** Mock API calls to isolate components and reducers during testing.
- **Stub Dependencies:** Stub external dependencies to control their behavior during testing.
## 6. Common Pitfalls and Gotchas:
- **Frequent Mistakes:**
- **Forgetting to Return State:** Reducers must always return the new state. If no change, return the original state.
- **Incorrectly Updating Nested Objects:** Remember to create copies of all levels when updating nested objects.
- **Not Handling Asynchronous Actions Correctly:** Using thunks or sagas incorrectly can lead to unexpected behavior.
- **Edge Cases:**
- **Initial State:** Ensure that the initial state is correctly defined.
- **Handling Errors:** Handle errors gracefully and provide informative error messages.
- **Empty States:** Handle empty states correctly to avoid unexpected behavior.
- **Version-Specific Issues:**
- **React Redux v8 vs v7:** Be aware of the changes introduced in React Redux v8, such as the improved performance and the new `useSyncExternalStore` hook.
- **Compatibility Concerns:**
- **Browser Compatibility:** Ensure that the application works correctly in all supported browsers.
- **Device Compatibility:** Ensure that the application works correctly on all supported devices.
- **Debugging Strategies:**
- **Redux DevTools:** Use the Redux DevTools extension to inspect the state and track actions.
- **Console Logging:** Use console logging to debug code and track state changes.
- **Debugging Tools:** Use browser debugging tools to step through code and inspect variables.
## 7. Tooling and Environment:
- **Recommended Development Tools:**
- **Redux DevTools Extension:** Inspect Redux state and actions.
- **VS Code with Redux Extension:** Provides code completion, linting, and debugging support for Redux.
- **Build Configuration:**
- **Webpack/Parcel/Rollup:** Use a module bundler to bundle the code and optimize it for production.
- **Babel:** Use Babel to transpile the code to older versions of JavaScript.
- **Linting and Formatting:**
- **ESLint:** Use ESLint to enforce code style and prevent errors.
- **Prettier:** Use Prettier to automatically format the code.
- **Deployment Best Practices:**
- **Environment Variables:** Use environment variables to configure the application for different environments.
- **CDN:** Use a CDN to serve static assets.
- **CI/CD Integration:**
- **Automated Testing:** Run tests automatically as part of the CI/CD pipeline.
- **Automated Deployment:** Deploy the application automatically to different environments.
This comprehensive guide should help you build robust, maintainable, and performant Redux applications. Remember to stay up-to-date with the latest best practices and tools in the Redux ecosystem.