Update documentation rules for various contexts and functionalities (#235)
Update cusor rules for various contexts and functionalities
This commit is contained in:
committed by
GitHub
parent
53b09fcb8e
commit
1030c84eee
224
.cursor/rules/react.mdc
Normal file
224
.cursor/rules/react.mdc
Normal file
@@ -0,0 +1,224 @@
|
||||
---
|
||||
description:
|
||||
globs: *.tsx
|
||||
alwaysApply: false
|
||||
---
|
||||
# React
|
||||
|
||||
## Core Principles
|
||||
|
||||
- **Component-Driven Development**: Build applications as a composition of isolated, reusable components
|
||||
- **One-Way Data Flow**: Follow React's unidirectional data flow pattern
|
||||
- **Single Responsibility**: Each component should have a clear, singular purpose
|
||||
- **TypeScript First**: Use TypeScript for type safety and better developer experience
|
||||
- **Internationalization (i18n) By Default**: All user-facing text should be translatable
|
||||
|
||||
## React Components
|
||||
|
||||
### Component Structure
|
||||
|
||||
- Always use functional components with TypeScript
|
||||
- Name components using PascalCase (e.g., `UserProfile`)
|
||||
- Use named exports for components, not default exports
|
||||
- Split components by responsibility and avoid "god components"
|
||||
- Name files to match their component name (e.g., `user-profile.tsx`)
|
||||
|
||||
### Props
|
||||
|
||||
- Always type props using TypeScript interfaces or type aliases
|
||||
- Use discriminated unions for complex prop types with conditional rendering
|
||||
- Destructure props at the start of component functions
|
||||
- Use prop spreading cautiously and only when appropriate
|
||||
- Provide default props for optional parameters when it makes sense
|
||||
|
||||
```typescript
|
||||
type ButtonProps = {
|
||||
variant: 'primary' | 'secondary' | 'ghost';
|
||||
size?: 'sm' | 'md' | 'lg';
|
||||
children: React.ReactNode;
|
||||
disabled?: boolean;
|
||||
onClick?: () => void;
|
||||
};
|
||||
|
||||
function Button({
|
||||
variant,
|
||||
size = 'md',
|
||||
children,
|
||||
disabled = false,
|
||||
onClick
|
||||
}: ButtonProps) {
|
||||
// Component implementation
|
||||
}
|
||||
```
|
||||
|
||||
### State Management
|
||||
|
||||
- Keep state as local as possible
|
||||
- Lift state up when multiple components need access
|
||||
- Use Context sparingly and only for truly global state
|
||||
- Prefer the "Container/Presenter" pattern when separating data and UI
|
||||
|
||||
```typescript
|
||||
// Container component (manages data)
|
||||
function UserProfileContainer() {
|
||||
const userData = useUserData();
|
||||
|
||||
if (userData.isLoading) {
|
||||
return <LoadingSpinner />;
|
||||
}
|
||||
|
||||
if (userData.error) {
|
||||
return <ErrorMessage error={userData.error} />;
|
||||
}
|
||||
|
||||
return <UserProfilePresenter data={userData.data} />;
|
||||
}
|
||||
|
||||
// Presenter component (renders UI)
|
||||
function UserProfilePresenter({ data }: { data: UserData }) {
|
||||
return (
|
||||
<div>
|
||||
<h1>{data.name}</h1>
|
||||
{/* Rest of the UI */}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### Hooks
|
||||
|
||||
- Follow the Rules of Hooks (only call hooks at the top level, only call them from React functions)
|
||||
- Create custom hooks for reusable logic
|
||||
- Keep custom hooks focused on a single concern
|
||||
- Name custom hooks with a 'use' prefix (e.g., `useUserProfile`)
|
||||
- Extract complex effect logic into separate functions
|
||||
- Always provide a complete dependencies array to `useEffect`
|
||||
|
||||
### Performance Optimization
|
||||
|
||||
- Apply `useMemo` for expensive calculations
|
||||
- Use `useCallback` for functions passed as props to child components
|
||||
- Split code using dynamic imports and `React.lazy()`
|
||||
|
||||
```typescript
|
||||
const MemoizedComponent = React.memo(function Component(props: Props) {
|
||||
// Component implementation
|
||||
});
|
||||
|
||||
// For expensive calculations
|
||||
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
|
||||
|
||||
// For callback functions passed as props
|
||||
const memoizedCallback = useCallback(() => {
|
||||
doSomething(a, b);
|
||||
}, [a, b]);
|
||||
```
|
||||
|
||||
### Internationalization (i18n)
|
||||
|
||||
- Always use the `Trans` component for text rendering (no hardcoded strings)
|
||||
- Ensure all i18n keys are available in locale files
|
||||
- Use namespaces to organize translations logically
|
||||
- Include interpolation variables in translation keys
|
||||
- Test UI with different languages, especially those with longer text
|
||||
|
||||
```typescript
|
||||
// Correct
|
||||
<Trans i18nKey="user:profile.welcomeMessage" values={{ name: user.name }} />
|
||||
|
||||
// Incorrect
|
||||
<p>Welcome, {user.name}!</p>
|
||||
```
|
||||
|
||||
## Server Components
|
||||
|
||||
### Fundamentals
|
||||
|
||||
- Server Components render React server-side and never run on the client
|
||||
- Use Server Components as the default choice, especially for data fetching
|
||||
- No use of hooks, browser APIs, or event handlers in Server Components
|
||||
- No use of `useState`, `useEffect`, or any other React hooks
|
||||
- Server Components can render Client Components but not vice versa
|
||||
|
||||
### Data Fetching
|
||||
|
||||
- Fetch data directly using async/await in Server Components
|
||||
- Use Suspense boundaries around data-fetching components
|
||||
- Apply security checks before fetching sensitive data
|
||||
- Never pass sensitive data (API keys, tokens) to Client Components
|
||||
- Use React's `cache()` function for caching data requests
|
||||
|
||||
### Error Handling
|
||||
|
||||
- Implement error boundaries at appropriate levels
|
||||
- Use the Next.js `error.tsx` file for route-level error handling
|
||||
- Create fallback UI for when data fetching fails
|
||||
- Log server errors appropriately without exposing details to clients
|
||||
|
||||
### Streaming and Suspense
|
||||
|
||||
- Use React Suspense for progressive loading experiences if specified
|
||||
- Implement streaming rendering for large or complex pages
|
||||
- Structure components to enable meaningful loading states
|
||||
- Prioritize above-the-fold content when using streaming
|
||||
|
||||
## Client Components
|
||||
|
||||
### Fundamentals
|
||||
|
||||
- Add the `'use client'` directive at the top of files for Client Components
|
||||
- Keep Client Components focused on interactivity and browser APIs
|
||||
- Use hooks appropriately following the Rules of Hooks
|
||||
- Implement controlled components for form elements
|
||||
- Handle all browser events in Client Components
|
||||
|
||||
### Data Fetching
|
||||
|
||||
- Use React Query (TanStack Query) for data fetching in Client Components
|
||||
- Create custom hooks for data fetching logic (e.g., `useUserData`)
|
||||
- Always handle loading, success, and error states
|
||||
|
||||
### Form Handling
|
||||
|
||||
- Use libraries like React Hook Form for complex forms
|
||||
- Implement proper validation with libraries like Zod
|
||||
- Create reusable form components
|
||||
- Handle form submissions with loading and error states
|
||||
- Use controlled components for form inputs
|
||||
|
||||
### Error Handling
|
||||
|
||||
- Implement error boundaries to catch and handle component errors if using client components
|
||||
- Always handle network request errors
|
||||
- Provide user-friendly error messages
|
||||
- Log errors appropriately
|
||||
- Implement retry mechanisms where applicable
|
||||
|
||||
```typescript
|
||||
'use client';
|
||||
|
||||
import { ErrorBoundary } from 'react-error-boundary';
|
||||
|
||||
function ErrorFallback({ error, resetErrorBoundary }) {
|
||||
return (
|
||||
<div role="alert">
|
||||
<p>Something went wrong:</p>
|
||||
<pre>{error.message}</pre>
|
||||
<button onClick={resetErrorBoundary}>Try again</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function UserProfileWithErrorHandling() {
|
||||
return (
|
||||
<ErrorBoundary
|
||||
FallbackComponent={ErrorFallback}
|
||||
onReset={() => {
|
||||
// Reset application state here if needed
|
||||
}}
|
||||
>
|
||||
<UserProfile userId="123" />
|
||||
</ErrorBoundary>
|
||||
);
|
||||
}
|
||||
```
|
||||
Reference in New Issue
Block a user