@esreekarreddy/ai-prompts 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +361 -0
- package/chains/_index.md +33 -0
- package/chains/bug-fix.md +222 -0
- package/chains/new-feature.md +216 -0
- package/chains/production-launch.md +291 -0
- package/chains/refactor.md +210 -0
- package/chains/security-hardening.md +242 -0
- package/contexts/guides/api-design.md +229 -0
- package/contexts/guides/error-handling.md +219 -0
- package/contexts/patterns/agentic-coding.md +368 -0
- package/contexts/patterns/mcp-server-patterns.md +267 -0
- package/contexts/patterns/repository-pattern.md +163 -0
- package/contexts/patterns/service-layer.md +185 -0
- package/contexts/stacks/fastapi.md +187 -0
- package/contexts/stacks/nextjs-14.md +149 -0
- package/contexts/stacks/prisma.md +228 -0
- package/dist/index.d.ts +129 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +284 -0
- package/dist/index.js.map +1 -0
- package/examples/architecture-docs/sample-architecture.md +270 -0
- package/examples/code-reviews/sample-review.md +232 -0
- package/examples/prds/sample-prd.md +179 -0
- package/instructions/_index.md +57 -0
- package/instructions/personas/code-reviewer.md +83 -0
- package/instructions/personas/devops-engineer.md +90 -0
- package/instructions/personas/security-expert.md +69 -0
- package/instructions/personas/senior-engineer.md +243 -0
- package/instructions/personas/ux-engineer.md +88 -0
- package/instructions/standards/fastapi.md +241 -0
- package/instructions/standards/go.md +427 -0
- package/instructions/standards/nextjs.md +350 -0
- package/instructions/standards/nodejs.md +284 -0
- package/instructions/standards/python.md +245 -0
- package/instructions/standards/react.md +227 -0
- package/instructions/standards/rust.md +318 -0
- package/instructions/standards/typescript-react.md +822 -0
- package/instructions/standards/typescript.md +294 -0
- package/instructions/workflows/feature-development.md +222 -0
- package/instructions/workflows/incident-response.md +192 -0
- package/instructions/workflows/pr-review.md +149 -0
- package/instructions/workflows/tdd.md +160 -0
- package/package.json +84 -0
- package/prompts/_index.md +70 -0
- package/prompts/agentic/agentic-loop.md +83 -0
- package/prompts/agentic/context-manager.md +37 -0
- package/prompts/agentic/test-driven-fix.md +41 -0
- package/prompts/analysis/deep-debugger.md +488 -0
- package/prompts/design/design-system-extractor.md +147 -0
- package/prompts/development/code-cleaner.md +119 -0
- package/prompts/development/debugger.md +64 -0
- package/prompts/development/tech-debt-audit.md +88 -0
- package/prompts/planning/architecture-analyzer.md +72 -0
- package/prompts/planning/implementation-plan.md +98 -0
- package/prompts/planning/prd-generator.md +66 -0
- package/prompts/planning/scope-killer.md +74 -0
- package/prompts/quality/critical-path-tester.md +133 -0
- package/prompts/quality/pre-launch-checklist.md +137 -0
- package/prompts/quality/security-audit.md +115 -0
- package/prompts/quality/security-fixer.md +117 -0
- package/prompts/quality/security-hardening.md +157 -0
- package/prompts/system/master-system-prompt.md +252 -0
- package/skills/_index.md +60 -0
- package/skills/code-review-advanced.md +435 -0
- package/skills/code-review.md +86 -0
- package/skills/debugging.md +86 -0
- package/skills/documentation.md +97 -0
- package/skills/pr-description.md +116 -0
- package/skills/project-setup.md +123 -0
- package/skills/refactoring.md +93 -0
- package/skills/testing.md +134 -0
- package/snippets/_index.md +57 -0
- package/snippets/constraints/mvp-only.md +50 -0
- package/snippets/constraints/no-external-deps.md +45 -0
- package/snippets/constraints/read-only.md +45 -0
- package/snippets/constraints/security-first.md +50 -0
- package/snippets/modifiers/be-ruthless.md +52 -0
- package/snippets/modifiers/be-thorough.md +50 -0
- package/snippets/modifiers/effort-high.md +56 -0
- package/snippets/modifiers/explain-reasoning.md +50 -0
- package/snippets/modifiers/megathink.md +314 -0
- package/snippets/modifiers/meta-cot.md +101 -0
- package/snippets/modifiers/no-code-yet.md +55 -0
- package/snippets/modifiers/step-by-step.md +50 -0
- package/snippets/modifiers/ultrathink.md +359 -0
- package/snippets/output-formats/checklist.md +61 -0
- package/snippets/output-formats/json.md +53 -0
- package/snippets/output-formats/markdown-table.md +44 -0
- package/snippets/output-formats/numbered-list.md +44 -0
- package/templates/_index.md +101 -0
- package/templates/claude-md/auto-enhance.md +258 -0
- package/templates/claude-md/cli-tool.md +243 -0
- package/templates/claude-md/full.md +449 -0
- package/templates/claude-md/minimal.md +52 -0
- package/templates/claude-md/nextjs-app.md +207 -0
- package/templates/claude-md/nodejs-service.md +251 -0
- package/templates/claude-md/python-api.md +236 -0
- package/templates/copilot/instructions.md +33 -0
- package/templates/cursor-rules/fullstack.txt +98 -0
- package/templates/cursor-rules/minimal.txt +20 -0
- package/templates/cursor-rules/nextjs.txt +61 -0
- package/templates/cursor-rules/python.txt +79 -0
- package/templates/docs/adr-template.md +119 -0
- package/templates/docs/api-spec-template.md +277 -0
- package/templates/docs/prd-template.md +140 -0
- package/templates/docs/runbook-template.md +238 -0
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
# Python Coding Standards
|
|
2
|
+
|
|
3
|
+
> Conventions for Python projects
|
|
4
|
+
|
|
5
|
+
## Python Version
|
|
6
|
+
|
|
7
|
+
- Target Python 3.11+
|
|
8
|
+
- Use modern features and syntax
|
|
9
|
+
|
|
10
|
+
## Type Hints
|
|
11
|
+
|
|
12
|
+
### Always Use Type Hints
|
|
13
|
+
```python
|
|
14
|
+
def get_user(user_id: int) -> User | None:
|
|
15
|
+
"""Get a user by ID."""
|
|
16
|
+
return db.query(User).filter(User.id == user_id).first()
|
|
17
|
+
|
|
18
|
+
async def create_user(data: UserCreate) -> User:
|
|
19
|
+
"""Create a new user."""
|
|
20
|
+
user = User(**data.model_dump())
|
|
21
|
+
db.add(user)
|
|
22
|
+
await db.commit()
|
|
23
|
+
return user
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### Common Types
|
|
27
|
+
```python
|
|
28
|
+
from typing import Any
|
|
29
|
+
from collections.abc import Sequence, Mapping
|
|
30
|
+
|
|
31
|
+
# Use | for unions (Python 3.10+)
|
|
32
|
+
def process(value: str | int | None) -> str:
|
|
33
|
+
...
|
|
34
|
+
|
|
35
|
+
# Generic containers
|
|
36
|
+
def get_items(ids: list[int]) -> list[Item]:
|
|
37
|
+
...
|
|
38
|
+
|
|
39
|
+
def get_config() -> dict[str, Any]:
|
|
40
|
+
...
|
|
41
|
+
|
|
42
|
+
# Callable
|
|
43
|
+
from collections.abc import Callable
|
|
44
|
+
def apply(func: Callable[[int], int], value: int) -> int:
|
|
45
|
+
return func(value)
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Naming Conventions
|
|
49
|
+
|
|
50
|
+
| Type | Convention | Example |
|
|
51
|
+
|------|------------|---------|
|
|
52
|
+
| Variables | snake_case | `user_count` |
|
|
53
|
+
| Functions | snake_case | `get_user_by_id` |
|
|
54
|
+
| Classes | PascalCase | `UserService` |
|
|
55
|
+
| Constants | SCREAMING_SNAKE | `MAX_RETRIES` |
|
|
56
|
+
| Private | _leading_underscore | `_internal_helper` |
|
|
57
|
+
| Modules | snake_case | `user_service.py` |
|
|
58
|
+
|
|
59
|
+
## Imports
|
|
60
|
+
|
|
61
|
+
```python
|
|
62
|
+
# Standard library
|
|
63
|
+
import os
|
|
64
|
+
from pathlib import Path
|
|
65
|
+
from typing import Any
|
|
66
|
+
|
|
67
|
+
# Third-party
|
|
68
|
+
from fastapi import FastAPI, Depends
|
|
69
|
+
from sqlalchemy.orm import Session
|
|
70
|
+
import httpx
|
|
71
|
+
|
|
72
|
+
# Local
|
|
73
|
+
from app.models import User
|
|
74
|
+
from app.services import user_service
|
|
75
|
+
from app.config import settings
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Order: standard library → third-party → local (separated by blank lines)
|
|
79
|
+
|
|
80
|
+
## Functions
|
|
81
|
+
|
|
82
|
+
### Docstrings
|
|
83
|
+
```python
|
|
84
|
+
def create_user(
|
|
85
|
+
email: str,
|
|
86
|
+
name: str,
|
|
87
|
+
*,
|
|
88
|
+
role: str = "user"
|
|
89
|
+
) -> User:
|
|
90
|
+
"""Create a new user in the database.
|
|
91
|
+
|
|
92
|
+
Args:
|
|
93
|
+
email: The user's email address.
|
|
94
|
+
name: The user's display name.
|
|
95
|
+
role: The user's role. Defaults to "user".
|
|
96
|
+
|
|
97
|
+
Returns:
|
|
98
|
+
The created User object.
|
|
99
|
+
|
|
100
|
+
Raises:
|
|
101
|
+
ValueError: If email is invalid.
|
|
102
|
+
DuplicateError: If email already exists.
|
|
103
|
+
"""
|
|
104
|
+
...
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Keyword-Only Arguments
|
|
108
|
+
```python
|
|
109
|
+
# Use * to require keyword arguments
|
|
110
|
+
def send_email(
|
|
111
|
+
to: str,
|
|
112
|
+
subject: str,
|
|
113
|
+
*, # Everything after is keyword-only
|
|
114
|
+
html: bool = False,
|
|
115
|
+
priority: str = "normal"
|
|
116
|
+
) -> None:
|
|
117
|
+
...
|
|
118
|
+
|
|
119
|
+
# Call with keywords
|
|
120
|
+
send_email("user@example.com", "Hello", html=True)
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## Error Handling
|
|
124
|
+
|
|
125
|
+
### Custom Exceptions
|
|
126
|
+
```python
|
|
127
|
+
class AppError(Exception):
|
|
128
|
+
"""Base exception for application errors."""
|
|
129
|
+
def __init__(self, message: str, code: str = "UNKNOWN"):
|
|
130
|
+
self.message = message
|
|
131
|
+
self.code = code
|
|
132
|
+
super().__init__(message)
|
|
133
|
+
|
|
134
|
+
class NotFoundError(AppError):
|
|
135
|
+
"""Raised when a resource is not found."""
|
|
136
|
+
def __init__(self, resource: str, id: Any):
|
|
137
|
+
super().__init__(f"{resource} with id {id} not found", "NOT_FOUND")
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### Try/Except
|
|
141
|
+
```python
|
|
142
|
+
# Be specific about exceptions
|
|
143
|
+
try:
|
|
144
|
+
result = risky_operation()
|
|
145
|
+
except ValueError as e:
|
|
146
|
+
logger.warning(f"Invalid value: {e}")
|
|
147
|
+
raise
|
|
148
|
+
except ConnectionError as e:
|
|
149
|
+
logger.error(f"Connection failed: {e}")
|
|
150
|
+
return None
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## Classes
|
|
154
|
+
|
|
155
|
+
### Dataclasses
|
|
156
|
+
```python
|
|
157
|
+
from dataclasses import dataclass, field
|
|
158
|
+
|
|
159
|
+
@dataclass
|
|
160
|
+
class User:
|
|
161
|
+
id: int
|
|
162
|
+
email: str
|
|
163
|
+
name: str
|
|
164
|
+
roles: list[str] = field(default_factory=list)
|
|
165
|
+
|
|
166
|
+
@property
|
|
167
|
+
def display_name(self) -> str:
|
|
168
|
+
return self.name or self.email
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### Pydantic Models
|
|
172
|
+
```python
|
|
173
|
+
from pydantic import BaseModel, EmailStr, Field
|
|
174
|
+
|
|
175
|
+
class UserCreate(BaseModel):
|
|
176
|
+
email: EmailStr
|
|
177
|
+
name: str = Field(..., min_length=2, max_length=100)
|
|
178
|
+
password: str = Field(..., min_length=8)
|
|
179
|
+
|
|
180
|
+
class UserResponse(BaseModel):
|
|
181
|
+
id: int
|
|
182
|
+
email: str
|
|
183
|
+
name: str
|
|
184
|
+
|
|
185
|
+
model_config = {"from_attributes": True}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## Best Practices
|
|
189
|
+
|
|
190
|
+
### Use pathlib
|
|
191
|
+
```python
|
|
192
|
+
from pathlib import Path
|
|
193
|
+
|
|
194
|
+
# Good
|
|
195
|
+
config_path = Path(__file__).parent / "config.json"
|
|
196
|
+
if config_path.exists():
|
|
197
|
+
content = config_path.read_text()
|
|
198
|
+
|
|
199
|
+
# Avoid
|
|
200
|
+
import os
|
|
201
|
+
config_path = os.path.join(os.path.dirname(__file__), "config.json")
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### Context Managers
|
|
205
|
+
```python
|
|
206
|
+
# Good
|
|
207
|
+
async with httpx.AsyncClient() as client:
|
|
208
|
+
response = await client.get(url)
|
|
209
|
+
|
|
210
|
+
# For custom resources
|
|
211
|
+
from contextlib import asynccontextmanager
|
|
212
|
+
|
|
213
|
+
@asynccontextmanager
|
|
214
|
+
async def get_connection():
|
|
215
|
+
conn = await create_connection()
|
|
216
|
+
try:
|
|
217
|
+
yield conn
|
|
218
|
+
finally:
|
|
219
|
+
await conn.close()
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### Comprehensions
|
|
223
|
+
```python
|
|
224
|
+
# List comprehension
|
|
225
|
+
squares = [x ** 2 for x in range(10)]
|
|
226
|
+
|
|
227
|
+
# With condition
|
|
228
|
+
evens = [x for x in range(10) if x % 2 == 0]
|
|
229
|
+
|
|
230
|
+
# Dict comprehension
|
|
231
|
+
user_map = {user.id: user for user in users}
|
|
232
|
+
|
|
233
|
+
# Generator for large data
|
|
234
|
+
large_sum = sum(x ** 2 for x in range(1000000))
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
## Anti-Patterns
|
|
238
|
+
|
|
239
|
+
| Avoid | Instead |
|
|
240
|
+
|-------|---------|
|
|
241
|
+
| Mutable default args | `= None` then `or []` |
|
|
242
|
+
| Bare `except:` | Specific exceptions |
|
|
243
|
+
| `type()` for type check | `isinstance()` |
|
|
244
|
+
| String concatenation in loops | `"".join()` |
|
|
245
|
+
| `== None` | `is None` |
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
# React Coding Standards
|
|
2
|
+
|
|
3
|
+
> Conventions for React components and hooks
|
|
4
|
+
|
|
5
|
+
## Component Structure
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
// 1. Imports
|
|
9
|
+
import { useState, useCallback } from 'react';
|
|
10
|
+
import { cn } from '@/lib/utils';
|
|
11
|
+
import { Button } from '@/components/ui/button';
|
|
12
|
+
import type { User } from '@/types';
|
|
13
|
+
|
|
14
|
+
// 2. Types
|
|
15
|
+
interface UserCardProps {
|
|
16
|
+
user: User;
|
|
17
|
+
onSelect?: (user: User) => void;
|
|
18
|
+
className?: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// 3. Component
|
|
22
|
+
export function UserCard({ user, onSelect, className }: UserCardProps) {
|
|
23
|
+
// 3a. Hooks (always at top)
|
|
24
|
+
const [isExpanded, setIsExpanded] = useState(false);
|
|
25
|
+
|
|
26
|
+
// 3b. Derived state
|
|
27
|
+
const displayName = `${user.firstName} ${user.lastName}`;
|
|
28
|
+
|
|
29
|
+
// 3c. Callbacks
|
|
30
|
+
const handleClick = useCallback(() => {
|
|
31
|
+
onSelect?.(user);
|
|
32
|
+
}, [user, onSelect]);
|
|
33
|
+
|
|
34
|
+
// 3d. Effects
|
|
35
|
+
useEffect(() => {
|
|
36
|
+
// Side effects
|
|
37
|
+
}, [dependencies]);
|
|
38
|
+
|
|
39
|
+
// 3e. Early returns
|
|
40
|
+
if (!user) return null;
|
|
41
|
+
|
|
42
|
+
// 3f. Render
|
|
43
|
+
return (
|
|
44
|
+
<div className={cn('p-4 rounded-lg', className)}>
|
|
45
|
+
<h3>{displayName}</h3>
|
|
46
|
+
<Button onClick={handleClick}>Select</Button>
|
|
47
|
+
</div>
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Naming Conventions
|
|
53
|
+
|
|
54
|
+
| Type | Convention | Example |
|
|
55
|
+
|------|------------|---------|
|
|
56
|
+
| Components | PascalCase | `UserCard` |
|
|
57
|
+
| Hooks | camelCase with 'use' | `useUserData` |
|
|
58
|
+
| Event handlers | handle* | `handleClick` |
|
|
59
|
+
| Boolean props | is*, has*, should* | `isLoading` |
|
|
60
|
+
| Files | kebab-case | `user-card.tsx` |
|
|
61
|
+
|
|
62
|
+
## Props
|
|
63
|
+
|
|
64
|
+
### Interface Over Type
|
|
65
|
+
```tsx
|
|
66
|
+
// Good
|
|
67
|
+
interface ButtonProps {
|
|
68
|
+
variant: 'primary' | 'secondary';
|
|
69
|
+
children: React.ReactNode;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Extend HTML attributes
|
|
73
|
+
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
74
|
+
variant: 'primary' | 'secondary';
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Default Props
|
|
79
|
+
```tsx
|
|
80
|
+
interface Props {
|
|
81
|
+
size?: 'sm' | 'md' | 'lg';
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function Component({ size = 'md' }: Props) {
|
|
85
|
+
// ...
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Children
|
|
90
|
+
```tsx
|
|
91
|
+
// Explicit children type
|
|
92
|
+
interface Props {
|
|
93
|
+
children: React.ReactNode;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Or for specific children
|
|
97
|
+
interface Props {
|
|
98
|
+
children: React.ReactElement<ChildProps>;
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Hooks
|
|
103
|
+
|
|
104
|
+
### Custom Hook Pattern
|
|
105
|
+
```tsx
|
|
106
|
+
// hooks/use-user.ts
|
|
107
|
+
export function useUser(userId: string) {
|
|
108
|
+
const [user, setUser] = useState<User | null>(null);
|
|
109
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
110
|
+
const [error, setError] = useState<Error | null>(null);
|
|
111
|
+
|
|
112
|
+
useEffect(() => {
|
|
113
|
+
let cancelled = false;
|
|
114
|
+
|
|
115
|
+
async function fetchUser() {
|
|
116
|
+
try {
|
|
117
|
+
const data = await api.getUser(userId);
|
|
118
|
+
if (!cancelled) setUser(data);
|
|
119
|
+
} catch (e) {
|
|
120
|
+
if (!cancelled) setError(e as Error);
|
|
121
|
+
} finally {
|
|
122
|
+
if (!cancelled) setIsLoading(false);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
fetchUser();
|
|
127
|
+
return () => { cancelled = true; };
|
|
128
|
+
}, [userId]);
|
|
129
|
+
|
|
130
|
+
return { user, isLoading, error };
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### Hook Rules
|
|
135
|
+
- Only call at top level (not in conditions/loops)
|
|
136
|
+
- Only call in React functions
|
|
137
|
+
- Prefix custom hooks with 'use'
|
|
138
|
+
- Return consistent shape
|
|
139
|
+
|
|
140
|
+
## State Management
|
|
141
|
+
|
|
142
|
+
### Local State
|
|
143
|
+
```tsx
|
|
144
|
+
// Simple state
|
|
145
|
+
const [count, setCount] = useState(0);
|
|
146
|
+
|
|
147
|
+
// Object state (prefer separate states)
|
|
148
|
+
const [form, setForm] = useState({ name: '', email: '' });
|
|
149
|
+
const updateField = (field: string, value: string) => {
|
|
150
|
+
setForm(prev => ({ ...prev, [field]: value }));
|
|
151
|
+
};
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Derived State (Don't Store)
|
|
155
|
+
```tsx
|
|
156
|
+
// Bad - storing derived state
|
|
157
|
+
const [items, setItems] = useState([]);
|
|
158
|
+
const [total, setTotal] = useState(0);
|
|
159
|
+
useEffect(() => {
|
|
160
|
+
setTotal(items.reduce((sum, i) => sum + i.price, 0));
|
|
161
|
+
}, [items]);
|
|
162
|
+
|
|
163
|
+
// Good - compute during render
|
|
164
|
+
const [items, setItems] = useState([]);
|
|
165
|
+
const total = items.reduce((sum, i) => sum + i.price, 0);
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
## Performance
|
|
169
|
+
|
|
170
|
+
### Memoization (When Needed)
|
|
171
|
+
```tsx
|
|
172
|
+
// Memoize expensive calculations
|
|
173
|
+
const sortedItems = useMemo(() => {
|
|
174
|
+
return [...items].sort((a, b) => a.name.localeCompare(b.name));
|
|
175
|
+
}, [items]);
|
|
176
|
+
|
|
177
|
+
// Memoize callbacks passed to children
|
|
178
|
+
const handleClick = useCallback(() => {
|
|
179
|
+
doSomething(id);
|
|
180
|
+
}, [id]);
|
|
181
|
+
|
|
182
|
+
// Memoize components (rare)
|
|
183
|
+
const MemoizedChild = memo(Child);
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### When NOT to Memoize
|
|
187
|
+
- Simple calculations
|
|
188
|
+
- Primitive values
|
|
189
|
+
- Callbacks not passed to children
|
|
190
|
+
- Components that always re-render anyway
|
|
191
|
+
|
|
192
|
+
## Common Patterns
|
|
193
|
+
|
|
194
|
+
### Conditional Rendering
|
|
195
|
+
```tsx
|
|
196
|
+
// Ternary for simple cases
|
|
197
|
+
{isLoading ? <Spinner /> : <Content />}
|
|
198
|
+
|
|
199
|
+
// && for presence check (careful with 0)
|
|
200
|
+
{items.length > 0 && <List items={items} />}
|
|
201
|
+
|
|
202
|
+
// Early return for complex conditions
|
|
203
|
+
if (isLoading) return <Spinner />;
|
|
204
|
+
if (error) return <Error error={error} />;
|
|
205
|
+
if (!data) return null;
|
|
206
|
+
return <Content data={data} />;
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### List Rendering
|
|
210
|
+
```tsx
|
|
211
|
+
// Always use unique, stable keys
|
|
212
|
+
{items.map(item => (
|
|
213
|
+
<ListItem key={item.id} item={item} />
|
|
214
|
+
))}
|
|
215
|
+
|
|
216
|
+
// Never use index as key (unless list is static)
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
### Compound Components
|
|
220
|
+
```tsx
|
|
221
|
+
// Flexible composition
|
|
222
|
+
<Card>
|
|
223
|
+
<Card.Header>Title</Card.Header>
|
|
224
|
+
<Card.Body>Content</Card.Body>
|
|
225
|
+
<Card.Footer>Actions</Card.Footer>
|
|
226
|
+
</Card>
|
|
227
|
+
```
|