vibes-plug 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.
Files changed (141) hide show
  1. package/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
  2. package/BLUEPRINT.md +125 -0
  3. package/CHANGELOG.md +195 -0
  4. package/CONTRIBUTING.md +199 -0
  5. package/LICENSE +21 -0
  6. package/README.md +263 -0
  7. package/SECURITY.md +21 -0
  8. package/banner.png +0 -0
  9. package/package.json +25 -0
  10. package/plugin.json +8 -0
  11. package/scripts/update_skills.js +75 -0
  12. package/skills/ai-llm-integration-expert/SKILL.md +162 -0
  13. package/skills/api-design-expert/SKILL.md +310 -0
  14. package/skills/app-analyzer-optimizer/SKILL.md +189 -0
  15. package/skills/asisten_ramah/SKILL.md +41 -0
  16. package/skills/authentication-identity-expert/SKILL.md +45 -0
  17. package/skills/auto-doc-updater/SKILL.md +204 -0
  18. package/skills/bootstrap-to-modern/SKILL.md +87 -0
  19. package/skills/brainstorming/SKILL.md +353 -0
  20. package/skills/bun-runtime-expert/SKILL.md +211 -0
  21. package/skills/ci-cd-devops-architect/SKILL.md +45 -0
  22. package/skills/cloud-hosting-expert/SKILL.md +244 -0
  23. package/skills/coderabbit/SKILL.md +192 -0
  24. package/skills/data-telemetry-expert/SKILL.md +213 -0
  25. package/skills/database-orm-expert/SKILL.md +294 -0
  26. package/skills/design-system-architect/SKILL.md +243 -0
  27. package/skills/e2e-testing-expert/SKILL.md +315 -0
  28. package/skills/event-driven-architect/SKILL.md +81 -0
  29. package/skills/firebase-security-expert/SKILL.md +195 -0
  30. package/skills/fullstack-expert/SKILL.md +202 -0
  31. package/skills/fullstack-expert/references/api_design_guide.md +466 -0
  32. package/skills/fullstack-expert/references/devops_infrastructure.md +477 -0
  33. package/skills/fullstack-expert/references/multi_language_backend.md +528 -0
  34. package/skills/fullstack-expert/references/system_design_patterns.md +358 -0
  35. package/skills/fullstack-expert/scripts/api_contract_validator.py +253 -0
  36. package/skills/fullstack-expert/scripts/architecture_analyzer.py +326 -0
  37. package/skills/gemini-agent-booster/SKILL.md +135 -0
  38. package/skills/global-a11y-i18n-expert/SKILL.md +81 -0
  39. package/skills/go-programming-expert/SKILL.md +295 -0
  40. package/skills/hig/SKILL.md +188 -0
  41. package/skills/js-backend-expert/SKILL.md +192 -0
  42. package/skills/mcp-server-architect/SKILL.md +194 -0
  43. package/skills/mobile-expo-expert/SKILL.md +186 -0
  44. package/skills/monday-design-aesthetic/SKILL.md +67 -0
  45. package/skills/monorepo-architect/SKILL.md +227 -0
  46. package/skills/mpa-orchestrator/SKILL.md +101 -0
  47. package/skills/multi-agent-orchestration/SKILL.md +234 -0
  48. package/skills/multiple-entry-points/SKILL.md +55 -0
  49. package/skills/mvc-expert/SKILL.md +231 -0
  50. package/skills/payment-gateway-expert/SKILL.md +45 -0
  51. package/skills/performance-web-vitals/SKILL.md +332 -0
  52. package/skills/prd-architect/SKILL.md +191 -0
  53. package/skills/production-ready-hardener/SKILL.md +469 -0
  54. package/skills/production-ready-hardener/references/performance_optimization.md +441 -0
  55. package/skills/production-ready-hardener/references/production_checklist.md +161 -0
  56. package/skills/production-ready-hardener/references/security_hardening_guide.md +379 -0
  57. package/skills/production-ready-hardener/scripts/production_readiness_scanner.py +875 -0
  58. package/skills/python-programming-expert/SKILL.md +271 -0
  59. package/skills/realtime-collaboration-expert/SKILL.md +45 -0
  60. package/skills/rust-programming-expert/SKILL.md +235 -0
  61. package/skills/saas-billing/SKILL.md +377 -0
  62. package/skills/saas-multi-tenant/SKILL.md +237 -0
  63. package/skills/saas-mvp-launcher/SKILL.md +231 -0
  64. package/skills/saas-transformer/SKILL.md +446 -0
  65. package/skills/saas-transformer/references/billing_integration_guide.md +401 -0
  66. package/skills/saas-transformer/references/feature_gating_patterns.md +137 -0
  67. package/skills/saas-transformer/references/saas_transformation_checklist.md +121 -0
  68. package/skills/saas-transformer/scripts/saas_transformation_scanner.py +254 -0
  69. package/skills/scalability-clean-code/SKILL.md +229 -0
  70. package/skills/secure-fuzz-testing/SKILL.md +201 -0
  71. package/skills/senior-frontend/SKILL.md +161 -0
  72. package/skills/senior-frontend/references/frontend_best_practices.md +806 -0
  73. package/skills/senior-frontend/references/nextjs_optimization_guide.md +724 -0
  74. package/skills/senior-frontend/references/react_patterns.md +746 -0
  75. package/skills/senior-frontend/scripts/bundle_analyzer.py +407 -0
  76. package/skills/senior-frontend/scripts/component_generator.py +329 -0
  77. package/skills/senior-frontend/scripts/frontend_scaffolder.py +1005 -0
  78. package/skills/senior-fullstack/SKILL.md +167 -0
  79. package/skills/senior-fullstack/references/architecture_patterns.md +160 -0
  80. package/skills/senior-fullstack/references/development_workflows.md +222 -0
  81. package/skills/senior-fullstack/references/tech_stack_guide.md +190 -0
  82. package/skills/senior-fullstack/scripts/code_quality_analyzer.py +114 -0
  83. package/skills/senior-fullstack/scripts/fullstack_scaffolder.py +114 -0
  84. package/skills/senior-fullstack/scripts/project_scaffolder.py +114 -0
  85. package/skills/seo/SKILL.md +225 -0
  86. package/skills/seo/references/cwv-thresholds.md +108 -0
  87. package/skills/seo/references/eeat-framework.md +214 -0
  88. package/skills/seo/references/quality-gates.md +155 -0
  89. package/skills/seo/references/schema-types.md +118 -0
  90. package/skills/seo-aeo-landing-page-writer/SKILL.md +97 -0
  91. package/skills/seo-geo/SKILL.md +188 -0
  92. package/skills/session-handoff-resume/SKILL.md +158 -0
  93. package/skills/skill_baru/SKILL.md +147 -0
  94. package/skills/spa-orchestrator/SKILL.md +288 -0
  95. package/skills/state-management-expert/SKILL.md +272 -0
  96. package/skills/supabase-migration/SKILL.md +45 -0
  97. package/skills/supabase-security-expert/SKILL.md +243 -0
  98. package/skills/tailwind-expert/SKILL.md +188 -0
  99. package/skills/tanstack-query-expert/SKILL.md +199 -0
  100. package/skills/tauri-expert/SKILL.md +97 -0
  101. package/skills/token-saver/SKILL.md +111 -0
  102. package/skills/typescript-expert/SKILL.md +279 -0
  103. package/skills/ui-components-expert/SKILL.md +63 -0
  104. package/skills/ui-ux-pro-max/SKILL.md +201 -0
  105. package/skills/ui-ux-pro-max/data/charts.csv +26 -0
  106. package/skills/ui-ux-pro-max/data/colors.csv +97 -0
  107. package/skills/ui-ux-pro-max/data/icons.csv +101 -0
  108. package/skills/ui-ux-pro-max/data/landing.csv +31 -0
  109. package/skills/ui-ux-pro-max/data/products.csv +97 -0
  110. package/skills/ui-ux-pro-max/data/prompts.csv +24 -0
  111. package/skills/ui-ux-pro-max/data/react-performance.csv +45 -0
  112. package/skills/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
  113. package/skills/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
  114. package/skills/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
  115. package/skills/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -0
  116. package/skills/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
  117. package/skills/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
  118. package/skills/ui-ux-pro-max/data/stacks/react.csv +54 -0
  119. package/skills/ui-ux-pro-max/data/stacks/shadcn.csv +61 -0
  120. package/skills/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
  121. package/skills/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
  122. package/skills/ui-ux-pro-max/data/stacks/vue.csv +50 -0
  123. package/skills/ui-ux-pro-max/data/styles.csv +59 -0
  124. package/skills/ui-ux-pro-max/data/typography.csv +58 -0
  125. package/skills/ui-ux-pro-max/data/ui-reasoning.csv +101 -0
  126. package/skills/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
  127. package/skills/ui-ux-pro-max/data/web-interface.csv +31 -0
  128. package/skills/ui-ux-pro-max/scripts/__pycache__/core.cpython-310.pyc +0 -0
  129. package/skills/ui-ux-pro-max/scripts/__pycache__/core.cpython-312.pyc +0 -0
  130. package/skills/ui-ux-pro-max/scripts/__pycache__/design_system.cpython-310.pyc +0 -0
  131. package/skills/ui-ux-pro-max/scripts/__pycache__/design_system.cpython-312.pyc +0 -0
  132. package/skills/ui-ux-pro-max/scripts/core.py +257 -0
  133. package/skills/ui-ux-pro-max/scripts/design_system.py +493 -0
  134. package/skills/ui-ux-pro-max/scripts/search.py +81 -0
  135. package/skills/ui_ux_expert/SKILL.md +114 -0
  136. package/skills/vibe-code-gardener/SKILL.md +173 -0
  137. package/skills/web-scraper/SKILL.md +205 -0
  138. package/skills/web-scraper/references/data-transforms.md +397 -0
  139. package/skills/web-scraper/references/extraction-patterns.md +475 -0
  140. package/skills/web-scraper/references/output-templates.md +481 -0
  141. package/skills/zero-to-prod-orchestrator/SKILL.md +180 -0
@@ -0,0 +1,746 @@
1
+ # React Patterns
2
+
3
+ Production-ready patterns for building scalable React applications with TypeScript.
4
+
5
+ ---
6
+
7
+ ## Table of Contents
8
+
9
+ - [Component Composition](#component-composition)
10
+ - [Custom Hooks](#custom-hooks)
11
+ - [State Management](#state-management)
12
+ - [Performance Patterns](#performance-patterns)
13
+ - [Error Boundaries](#error-boundaries)
14
+ - [Anti-Patterns](#anti-patterns)
15
+
16
+ ---
17
+
18
+ ## Component Composition
19
+
20
+ ### Compound Components
21
+
22
+ Use compound components when building reusable UI components with multiple related parts.
23
+
24
+ ```tsx
25
+ // Compound component pattern for a Select
26
+ interface SelectContextType {
27
+ value: string;
28
+ onChange: (value: string) => void;
29
+ }
30
+
31
+ const SelectContext = createContext<SelectContextType | null>(null);
32
+
33
+ function Select({ children, value, onChange }: {
34
+ children: React.ReactNode;
35
+ value: string;
36
+ onChange: (value: string) => void;
37
+ }) {
38
+ return (
39
+ <SelectContext.Provider value={{ value, onChange }}>
40
+ <div className="relative">{children}</div>
41
+ </SelectContext.Provider>
42
+ );
43
+ }
44
+
45
+ function SelectTrigger({ children }: { children: React.ReactNode }) {
46
+ const context = useContext(SelectContext);
47
+ if (!context) throw new Error('SelectTrigger must be used within Select');
48
+
49
+ return (
50
+ <button className="flex items-center gap-2 px-4 py-2 border rounded">
51
+ {children}
52
+ </button>
53
+ );
54
+ }
55
+
56
+ function SelectOption({ value, children }: { value: string; children: React.ReactNode }) {
57
+ const context = useContext(SelectContext);
58
+ if (!context) throw new Error('SelectOption must be used within Select');
59
+
60
+ return (
61
+ <div
62
+ onClick={() => context.onChange(value)}
63
+ className={`px-4 py-2 cursor-pointer hover:bg-gray-100 ${
64
+ context.value === value ? 'bg-blue-50' : ''
65
+ }`}
66
+ >
67
+ {children}
68
+ </div>
69
+ );
70
+ }
71
+
72
+ // Attach sub-components
73
+ Select.Trigger = SelectTrigger;
74
+ Select.Option = SelectOption;
75
+
76
+ // Usage
77
+ <Select value={selected} onChange={setSelected}>
78
+ <Select.Trigger>Choose option</Select.Trigger>
79
+ <Select.Option value="a">Option A</Select.Option>
80
+ <Select.Option value="b">Option B</Select.Option>
81
+ </Select>
82
+ ```
83
+
84
+ ### Render Props
85
+
86
+ Use render props when you need to share behavior with flexible rendering.
87
+
88
+ ```tsx
89
+ interface MousePosition {
90
+ x: number;
91
+ y: number;
92
+ }
93
+
94
+ function MouseTracker({ render }: { render: (pos: MousePosition) => React.ReactNode }) {
95
+ const [position, setPosition] = useState<MousePosition>({ x: 0, y: 0 });
96
+
97
+ useEffect(() => {
98
+ const handleMouseMove = (e: MouseEvent) => {
99
+ setPosition({ x: e.clientX, y: e.clientY });
100
+ };
101
+ window.addEventListener('mousemove', handleMouseMove);
102
+ return () => window.removeEventListener('mousemove', handleMouseMove);
103
+ }, []);
104
+
105
+ return <>{render(position)}</>;
106
+ }
107
+
108
+ // Usage
109
+ <MouseTracker
110
+ render={({ x, y }) => (
111
+ <div>Mouse position: {x}, {y}</div>
112
+ )}
113
+ />
114
+ ```
115
+
116
+ ### Higher-Order Components (HOC)
117
+
118
+ Use HOCs for cross-cutting concerns like authentication or logging.
119
+
120
+ ```tsx
121
+ function withAuth<P extends object>(WrappedComponent: React.ComponentType<P>) {
122
+ return function AuthenticatedComponent(props: P) {
123
+ const { user, isLoading } = useAuth();
124
+
125
+ if (isLoading) return <LoadingSpinner />;
126
+ if (!user) return <Navigate to="/login" />;
127
+
128
+ return <WrappedComponent {...props} />;
129
+ };
130
+ }
131
+
132
+ // Usage
133
+ const ProtectedDashboard = withAuth(Dashboard);
134
+ ```
135
+
136
+ ---
137
+
138
+ ## Custom Hooks
139
+
140
+ ### useAsync - Handle async operations
141
+
142
+ ```tsx
143
+ interface AsyncState<T> {
144
+ data: T | null;
145
+ error: Error | null;
146
+ status: 'idle' | 'loading' | 'success' | 'error';
147
+ }
148
+
149
+ function useAsync<T>(asyncFn: () => Promise<T>, deps: any[] = []) {
150
+ const [state, setState] = useState<AsyncState<T>>({
151
+ data: null,
152
+ error: null,
153
+ status: 'idle',
154
+ });
155
+
156
+ const execute = useCallback(async () => {
157
+ setState({ data: null, error: null, status: 'loading' });
158
+ try {
159
+ const data = await asyncFn();
160
+ setState({ data, error: null, status: 'success' });
161
+ } catch (error) {
162
+ setState({ data: null, error: error as Error, status: 'error' });
163
+ }
164
+ }, deps);
165
+
166
+ useEffect(() => {
167
+ execute();
168
+ }, [execute]);
169
+
170
+ return { ...state, refetch: execute };
171
+ }
172
+
173
+ // Usage
174
+ function UserProfile({ userId }: { userId: string }) {
175
+ const { data: user, status, error, refetch } = useAsync(
176
+ () => fetchUser(userId),
177
+ [userId]
178
+ );
179
+
180
+ if (status === 'loading') return <Spinner />;
181
+ if (status === 'error') return <Error message={error?.message} />;
182
+ if (!user) return null;
183
+
184
+ return <Profile user={user} />;
185
+ }
186
+ ```
187
+
188
+ ### useDebounce - Debounce values
189
+
190
+ ```tsx
191
+ function useDebounce<T>(value: T, delay: number): T {
192
+ const [debouncedValue, setDebouncedValue] = useState(value);
193
+
194
+ useEffect(() => {
195
+ const timer = setTimeout(() => setDebouncedValue(value), delay);
196
+ return () => clearTimeout(timer);
197
+ }, [value, delay]);
198
+
199
+ return debouncedValue;
200
+ }
201
+
202
+ // Usage
203
+ function SearchInput() {
204
+ const [query, setQuery] = useState('');
205
+ const debouncedQuery = useDebounce(query, 300);
206
+
207
+ useEffect(() => {
208
+ if (debouncedQuery) {
209
+ searchAPI(debouncedQuery);
210
+ }
211
+ }, [debouncedQuery]);
212
+
213
+ return <input value={query} onChange={(e) => setQuery(e.target.value)} />;
214
+ }
215
+ ```
216
+
217
+ ### useLocalStorage - Persist state
218
+
219
+ ```tsx
220
+ function useLocalStorage<T>(key: string, initialValue: T) {
221
+ const [storedValue, setStoredValue] = useState<T>(() => {
222
+ if (typeof window === 'undefined') return initialValue;
223
+ try {
224
+ const item = window.localStorage.getItem(key);
225
+ return item ? JSON.parse(item) : initialValue;
226
+ } catch {
227
+ return initialValue;
228
+ }
229
+ });
230
+
231
+ const setValue = useCallback((value: T | ((val: T) => T)) => {
232
+ try {
233
+ const valueToStore = value instanceof Function ? value(storedValue) : value;
234
+ setStoredValue(valueToStore);
235
+ if (typeof window !== 'undefined') {
236
+ window.localStorage.setItem(key, JSON.stringify(valueToStore));
237
+ }
238
+ } catch (error) {
239
+ console.error('Error saving to localStorage:', error);
240
+ }
241
+ }, [key, storedValue]);
242
+
243
+ return [storedValue, setValue] as const;
244
+ }
245
+
246
+ // Usage
247
+ const [theme, setTheme] = useLocalStorage('theme', 'light');
248
+ ```
249
+
250
+ ### useMediaQuery - Responsive design
251
+
252
+ ```tsx
253
+ function useMediaQuery(query: string): boolean {
254
+ const [matches, setMatches] = useState(false);
255
+
256
+ useEffect(() => {
257
+ const media = window.matchMedia(query);
258
+ setMatches(media.matches);
259
+
260
+ const listener = (e: MediaQueryListEvent) => setMatches(e.matches);
261
+ media.addEventListener('change', listener);
262
+ return () => media.removeEventListener('change', listener);
263
+ }, [query]);
264
+
265
+ return matches;
266
+ }
267
+
268
+ // Usage
269
+ function ResponsiveNav() {
270
+ const isMobile = useMediaQuery('(max-width: 768px)');
271
+ return isMobile ? <MobileNav /> : <DesktopNav />;
272
+ }
273
+ ```
274
+
275
+ ### usePrevious - Track previous values
276
+
277
+ ```tsx
278
+ function usePrevious<T>(value: T): T | undefined {
279
+ const ref = useRef<T>();
280
+
281
+ useEffect(() => {
282
+ ref.current = value;
283
+ }, [value]);
284
+
285
+ return ref.current;
286
+ }
287
+
288
+ // Usage
289
+ function Counter() {
290
+ const [count, setCount] = useState(0);
291
+ const prevCount = usePrevious(count);
292
+
293
+ return (
294
+ <div>
295
+ Current: {count}, Previous: {prevCount}
296
+ </div>
297
+ );
298
+ }
299
+ ```
300
+
301
+ ---
302
+
303
+ ## State Management
304
+
305
+ ### Context with Reducer
306
+
307
+ For complex state that multiple components need to access.
308
+
309
+ ```tsx
310
+ // types.ts
311
+ interface CartItem {
312
+ id: string;
313
+ name: string;
314
+ price: number;
315
+ quantity: number;
316
+ }
317
+
318
+ interface CartState {
319
+ items: CartItem[];
320
+ total: number;
321
+ }
322
+
323
+ type CartAction =
324
+ | { type: 'ADD_ITEM'; payload: CartItem }
325
+ | { type: 'REMOVE_ITEM'; payload: string }
326
+ | { type: 'UPDATE_QUANTITY'; payload: { id: string; quantity: number } }
327
+ | { type: 'CLEAR_CART' };
328
+
329
+ // reducer.ts
330
+ function cartReducer(state: CartState, action: CartAction): CartState {
331
+ switch (action.type) {
332
+ case 'ADD_ITEM': {
333
+ const existingItem = state.items.find(i => i.id === action.payload.id);
334
+ if (existingItem) {
335
+ return {
336
+ ...state,
337
+ items: state.items.map(item =>
338
+ item.id === action.payload.id
339
+ ? { ...item, quantity: item.quantity + 1 }
340
+ : item
341
+ ),
342
+ };
343
+ }
344
+ return {
345
+ ...state,
346
+ items: [...state.items, { ...action.payload, quantity: 1 }],
347
+ };
348
+ }
349
+ case 'REMOVE_ITEM':
350
+ return {
351
+ ...state,
352
+ items: state.items.filter(i => i.id !== action.payload),
353
+ };
354
+ case 'UPDATE_QUANTITY':
355
+ return {
356
+ ...state,
357
+ items: state.items.map(item =>
358
+ item.id === action.payload.id
359
+ ? { ...item, quantity: action.payload.quantity }
360
+ : item
361
+ ),
362
+ };
363
+ case 'CLEAR_CART':
364
+ return { items: [], total: 0 };
365
+ default:
366
+ return state;
367
+ }
368
+ }
369
+
370
+ // context.tsx
371
+ const CartContext = createContext<{
372
+ state: CartState;
373
+ dispatch: React.Dispatch<CartAction>;
374
+ } | null>(null);
375
+
376
+ function CartProvider({ children }: { children: React.ReactNode }) {
377
+ const [state, dispatch] = useReducer(cartReducer, { items: [], total: 0 });
378
+
379
+ // Compute total whenever items change
380
+ const stateWithTotal = useMemo(() => ({
381
+ ...state,
382
+ total: state.items.reduce((sum, item) => sum + item.price * item.quantity, 0),
383
+ }), [state.items]);
384
+
385
+ return (
386
+ <CartContext.Provider value={{ state: stateWithTotal, dispatch }}>
387
+ {children}
388
+ </CartContext.Provider>
389
+ );
390
+ }
391
+
392
+ function useCart() {
393
+ const context = useContext(CartContext);
394
+ if (!context) throw new Error('useCart must be used within CartProvider');
395
+ return context;
396
+ }
397
+ ```
398
+
399
+ ### Zustand (Lightweight Alternative)
400
+
401
+ ```tsx
402
+ import { create } from 'zustand';
403
+ import { persist } from 'zustand/middleware';
404
+
405
+ interface AuthStore {
406
+ user: User | null;
407
+ token: string | null;
408
+ login: (email: string, password: string) => Promise<void>;
409
+ logout: () => void;
410
+ }
411
+
412
+ const useAuthStore = create<AuthStore>()(
413
+ persist(
414
+ (set) => ({
415
+ user: null,
416
+ token: null,
417
+ login: async (email, password) => {
418
+ const { user, token } = await authAPI.login(email, password);
419
+ set({ user, token });
420
+ },
421
+ logout: () => set({ user: null, token: null }),
422
+ }),
423
+ { name: 'auth-storage' }
424
+ )
425
+ );
426
+
427
+ // Usage
428
+ function Profile() {
429
+ const { user, logout } = useAuthStore();
430
+ return user ? <div>{user.name} <button onClick={logout}>Logout</button></div> : null;
431
+ }
432
+ ```
433
+
434
+ ---
435
+
436
+ ## Performance Patterns
437
+
438
+ ### React.memo with Custom Comparison
439
+
440
+ ```tsx
441
+ interface ListItemProps {
442
+ item: { id: string; name: string; count: number };
443
+ onSelect: (id: string) => void;
444
+ }
445
+
446
+ const ListItem = React.memo(
447
+ function ListItem({ item, onSelect }: ListItemProps) {
448
+ return (
449
+ <div onClick={() => onSelect(item.id)}>
450
+ {item.name} ({item.count})
451
+ </div>
452
+ );
453
+ },
454
+ (prevProps, nextProps) => {
455
+ // Only re-render if item data changed
456
+ return (
457
+ prevProps.item.id === nextProps.item.id &&
458
+ prevProps.item.name === nextProps.item.name &&
459
+ prevProps.item.count === nextProps.item.count
460
+ );
461
+ }
462
+ );
463
+ ```
464
+
465
+ ### useMemo for Expensive Calculations
466
+
467
+ ```tsx
468
+ function DataTable({ data, sortColumn, filterText }: {
469
+ data: Item[];
470
+ sortColumn: string;
471
+ filterText: string;
472
+ }) {
473
+ const processedData = useMemo(() => {
474
+ // Filter
475
+ let result = data.filter(item =>
476
+ item.name.toLowerCase().includes(filterText.toLowerCase())
477
+ );
478
+
479
+ // Sort
480
+ result = [...result].sort((a, b) => {
481
+ const aVal = a[sortColumn as keyof Item];
482
+ const bVal = b[sortColumn as keyof Item];
483
+ return aVal < bVal ? -1 : aVal > bVal ? 1 : 0;
484
+ });
485
+
486
+ return result;
487
+ }, [data, sortColumn, filterText]);
488
+
489
+ return (
490
+ <table>
491
+ {processedData.map(item => (
492
+ <tr key={item.id}>{/* ... */}</tr>
493
+ ))}
494
+ </table>
495
+ );
496
+ }
497
+ ```
498
+
499
+ ### useCallback for Stable References
500
+
501
+ ```tsx
502
+ function ParentComponent() {
503
+ const [items, setItems] = useState<Item[]>([]);
504
+
505
+ // Stable reference - won't cause child re-renders
506
+ const handleItemClick = useCallback((id: string) => {
507
+ setItems(prev => prev.map(item =>
508
+ item.id === id ? { ...item, selected: !item.selected } : item
509
+ ));
510
+ }, []);
511
+
512
+ const handleAddItem = useCallback((newItem: Item) => {
513
+ setItems(prev => [...prev, newItem]);
514
+ }, []);
515
+
516
+ return (
517
+ <>
518
+ <ItemList items={items} onItemClick={handleItemClick} />
519
+ <AddItemForm onAdd={handleAddItem} />
520
+ </>
521
+ );
522
+ }
523
+ ```
524
+
525
+ ### Virtualization for Long Lists
526
+
527
+ ```tsx
528
+ import { useVirtualizer } from '@tanstack/react-virtual';
529
+
530
+ function VirtualList({ items }: { items: Item[] }) {
531
+ const parentRef = useRef<HTMLDivElement>(null);
532
+
533
+ const virtualizer = useVirtualizer({
534
+ count: items.length,
535
+ getScrollElement: () => parentRef.current,
536
+ estimateSize: () => 50, // estimated row height
537
+ overscan: 5,
538
+ });
539
+
540
+ return (
541
+ <div ref={parentRef} className="h-[400px] overflow-auto">
542
+ <div
543
+ style={{ height: `${virtualizer.getTotalSize()}px`, position: 'relative' }}
544
+ >
545
+ {virtualizer.getVirtualItems().map(virtualRow => (
546
+ <div
547
+ key={virtualRow.key}
548
+ style={{
549
+ position: 'absolute',
550
+ top: 0,
551
+ left: 0,
552
+ width: '100%',
553
+ height: `${virtualRow.size}px`,
554
+ transform: `translateY(${virtualRow.start}px)`,
555
+ }}
556
+ >
557
+ {items[virtualRow.index].name}
558
+ </div>
559
+ ))}
560
+ </div>
561
+ </div>
562
+ );
563
+ }
564
+ ```
565
+
566
+ ---
567
+
568
+ ## Error Boundaries
569
+
570
+ ### Class-Based Error Boundary
571
+
572
+ ```tsx
573
+ interface ErrorBoundaryProps {
574
+ children: React.ReactNode;
575
+ fallback?: React.ReactNode;
576
+ onError?: (error: Error, errorInfo: React.ErrorInfo) => void;
577
+ }
578
+
579
+ interface ErrorBoundaryState {
580
+ hasError: boolean;
581
+ error: Error | null;
582
+ }
583
+
584
+ class ErrorBoundary extends React.Component<ErrorBoundaryProps, ErrorBoundaryState> {
585
+ state: ErrorBoundaryState = { hasError: false, error: null };
586
+
587
+ static getDerivedStateFromError(error: Error): ErrorBoundaryState {
588
+ return { hasError: true, error };
589
+ }
590
+
591
+ componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
592
+ this.props.onError?.(error, errorInfo);
593
+ // Log to error reporting service
594
+ console.error('Error caught:', error, errorInfo);
595
+ }
596
+
597
+ render() {
598
+ if (this.state.hasError) {
599
+ return this.props.fallback || (
600
+ <div className="p-4 bg-red-50 border border-red-200 rounded">
601
+ <h2 className="text-red-800 font-bold">Something went wrong</h2>
602
+ <p className="text-red-600">{this.state.error?.message}</p>
603
+ <button
604
+ onClick={() => this.setState({ hasError: false, error: null })}
605
+ className="mt-2 px-4 py-2 bg-red-600 text-white rounded"
606
+ >
607
+ Try Again
608
+ </button>
609
+ </div>
610
+ );
611
+ }
612
+
613
+ return this.props.children;
614
+ }
615
+ }
616
+
617
+ // Usage
618
+ <ErrorBoundary
619
+ fallback={<ErrorFallback />}
620
+ onError={(error) => trackError(error)}
621
+ >
622
+ <MyComponent />
623
+ </ErrorBoundary>
624
+ ```
625
+
626
+ ### Suspense with Error Boundary
627
+
628
+ ```tsx
629
+ function DataComponent() {
630
+ return (
631
+ <ErrorBoundary fallback={<ErrorMessage />}>
632
+ <Suspense fallback={<LoadingSpinner />}>
633
+ <AsyncDataLoader />
634
+ </Suspense>
635
+ </ErrorBoundary>
636
+ );
637
+ }
638
+ ```
639
+
640
+ ---
641
+
642
+ ## Anti-Patterns
643
+
644
+ ### Avoid: Inline Object/Array Creation in JSX
645
+
646
+ ```tsx
647
+ // BAD - Creates new object every render, causes re-renders
648
+ <Component style={{ color: 'red' }} items={[1, 2, 3]} />
649
+
650
+ // GOOD - Define outside or use useMemo
651
+ const style = { color: 'red' };
652
+ const items = [1, 2, 3];
653
+ <Component style={style} items={items} />
654
+
655
+ // Or with useMemo for dynamic values
656
+ const style = useMemo(() => ({ color: theme.primary }), [theme.primary]);
657
+ ```
658
+
659
+ ### Avoid: Index as Key for Dynamic Lists
660
+
661
+ ```tsx
662
+ // BAD - Index keys break with reordering/filtering
663
+ {items.map((item, index) => (
664
+ <Item key={index} data={item} />
665
+ ))}
666
+
667
+ // GOOD - Use stable unique ID
668
+ {items.map(item => (
669
+ <Item key={item.id} data={item} />
670
+ ))}
671
+ ```
672
+
673
+ ### Avoid: Prop Drilling
674
+
675
+ ```tsx
676
+ // BAD - Passing props through many levels
677
+ <App user={user}>
678
+ <Layout user={user}>
679
+ <Sidebar user={user}>
680
+ <UserInfo user={user} />
681
+ </Sidebar>
682
+ </Layout>
683
+ </App>
684
+
685
+ // GOOD - Use Context
686
+ const UserContext = createContext<User | null>(null);
687
+
688
+ function App() {
689
+ return (
690
+ <UserContext.Provider value={user}>
691
+ <Layout>
692
+ <Sidebar>
693
+ <UserInfo />
694
+ </Sidebar>
695
+ </Layout>
696
+ </UserContext.Provider>
697
+ );
698
+ }
699
+
700
+ function UserInfo() {
701
+ const user = useContext(UserContext);
702
+ return <div>{user?.name}</div>;
703
+ }
704
+ ```
705
+
706
+ ### Avoid: Mutating State Directly
707
+
708
+ ```tsx
709
+ // BAD - Mutates state directly
710
+ const addItem = (item: Item) => {
711
+ items.push(item); // WRONG
712
+ setItems(items); // Won't trigger re-render
713
+ };
714
+
715
+ // GOOD - Create new array
716
+ const addItem = (item: Item) => {
717
+ setItems(prev => [...prev, item]);
718
+ };
719
+
720
+ // GOOD - For objects
721
+ const updateUser = (field: string, value: string) => {
722
+ setUser(prev => ({ ...prev, [field]: value }));
723
+ };
724
+ ```
725
+
726
+ ### Avoid: useEffect for Derived State
727
+
728
+ ```tsx
729
+ // BAD - Unnecessary effect and extra render
730
+ const [items, setItems] = useState<Item[]>([]);
731
+ const [total, setTotal] = useState(0);
732
+
733
+ useEffect(() => {
734
+ setTotal(items.reduce((sum, item) => sum + item.price, 0));
735
+ }, [items]);
736
+
737
+ // GOOD - Compute during render
738
+ const [items, setItems] = useState<Item[]>([]);
739
+ const total = items.reduce((sum, item) => sum + item.price, 0);
740
+
741
+ // Or useMemo for expensive calculations
742
+ const total = useMemo(
743
+ () => items.reduce((sum, item) => sum + item.price, 0),
744
+ [items]
745
+ );
746
+ ```