Expert JavaScript & React Development
Write modern, performant, type-safe JavaScript and React code following current best practices.
Core Principles
-
Prefer composition over inheritance - Use hooks, HOCs, and render props strategically
-
Minimize re-renders - Memoize appropriately, lift state only when necessary
-
Type everything - Use TypeScript for any non-trivial code
-
Fail fast - Validate inputs, use error boundaries, handle edge cases
JavaScript Patterns
Modern Syntax Defaults
// Prefer const, use let only when reassignment needed const config = { timeout: 5000 }; let count = 0;
// Destructuring with defaults const { name, age = 18, ...rest } = user; const [first, second, ...remaining] = items;
// Optional chaining and nullish coalescing const value = obj?.deeply?.nested?.value ?? 'default';
// Template literals for complex strings
const query = SELECT * FROM ${table} WHERE id = ${id};
Async Patterns
// Prefer async/await over raw promises
async function fetchData(url) {
try {
const response = await fetch(url);
if (!response.ok) throw new Error(HTTP ${response.status});
return await response.json();
} catch (error) {
console.error('Fetch failed:', error);
throw error;
}
}
// Parallel execution const [users, posts] = await Promise.all([fetchUsers(), fetchPosts()]);
// Sequential with error handling const results = await Promise.allSettled([task1(), task2(), task3()]); const successes = results.filter(r => r.status === 'fulfilled').map(r => r.value);
Advanced patterns reference
See references/modern-javascript.md for:
-
Closures and module patterns
-
Proxy and Reflect
-
Generators and async iterators
-
WeakMap/WeakSet for memory management
-
Custom iterables
React Patterns
Component Structure
// Functional components with TypeScript interface ButtonProps { variant?: 'primary' | 'secondary' | 'danger'; size?: 'sm' | 'md' | 'lg'; disabled?: boolean; onClick?: () => void; children: React.ReactNode; }
export function Button({ variant = 'primary', size = 'md', disabled = false, onClick, children, }: ButtonProps) { return ( <button className={cn(styles.button, styles[variant], styles[size])} disabled={disabled} onClick={onClick} > {children} </button> ); }
Hooks Best Practices
// Custom hooks extract reusable logic function useDebounce<T>(value: T, delay: number): T { const [debouncedValue, setDebouncedValue] = useState(value);
useEffect(() => { const timer = setTimeout(() => setDebouncedValue(value), delay); return () => clearTimeout(timer); }, [value, delay]);
return debouncedValue; }
// useMemo for expensive computations const sortedItems = useMemo( () => items.slice().sort((a, b) => a.name.localeCompare(b.name)), [items] );
// useCallback for stable function references const handleSubmit = useCallback( async (data: FormData) => { await submitForm(data); onSuccess(); }, [onSuccess] );
State Management Decision Tree
-
Local UI state → useState
-
Complex local state with actions → useReducer
-
Shared state within subtree → Context + useReducer
-
Global app state → Zustand, Jotai, or Redux Toolkit
-
Server state (fetching/caching) → TanStack Query or SWR
Advanced React patterns reference
See references/react-patterns.md for:
-
Compound components
-
Render props and HOCs
-
Controlled vs uncontrolled patterns
-
Error boundaries
-
Suspense and lazy loading
-
Server components (React 19+)
TypeScript Patterns
Type Utilities
// Discriminated unions for exhaustive checking type Result<T> = { ok: true; value: T } | { ok: false; error: Error };
// Generic constraints function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] { return obj[key]; }
// Conditional types type Awaited<T> = T extends Promise<infer U> ? U : T;
// Template literal types
type EventName = on${Capitalize<string>};
Strict Configuration
{ "compilerOptions": { "strict": true, "noUncheckedIndexedAccess": true, "noImplicitReturns": true, "exactOptionalPropertyTypes": true } }
Performance Optimization
See references/performance.md for comprehensive optimization strategies.
Quick Reference
Problem Solution
Unnecessary re-renders React.memo , useMemo , useCallback
Large bundle size Code splitting, React.lazy , tree shaking
Slow lists Virtualization (@tanstack/react-virtual )
Layout thrashing useLayoutEffect , batch DOM reads
Memory leaks Cleanup in useEffect , AbortController
Critical Anti-patterns
// ❌ Creating objects/arrays in render <Component style={{ color: 'red' }} items={[1, 2, 3]} />
// ✅ Stable references const style = useMemo(() => ({ color: 'red' }), []); const items = useMemo(() => [1, 2, 3], []);
// ❌ Index as key with dynamic lists {items.map((item, i) => <Item key={i} {...item} />)}
// ✅ Stable unique keys {items.map(item => <Item key={item.id} {...item} />)}
Testing
See references/testing.md for testing strategies.
Testing Stack
-
Unit tests: Vitest (fast, ESM-native)
-
Component tests: React Testing Library
-
E2E tests: Playwright
-
Type tests: tsd or expect-type
Testing Principles
-
Test behavior, not implementation
-
Prefer integration tests over unit tests
-
Mock at network boundary (MSW), not internal modules
-
Use realistic data with factories
Project Structure
src/ ├── components/ # Reusable UI components │ └── Button/ │ ├── Button.tsx │ ├── Button.test.tsx │ └── index.ts ├── features/ # Feature-specific code │ └── auth/ │ ├── components/ │ ├── hooks/ │ ├── api.ts │ └── types.ts ├── hooks/ # Shared custom hooks ├── lib/ # Utilities and helpers ├── types/ # Shared TypeScript types └── App.tsx
Tooling Recommendations
Category Tool Notes
Build Vite Fast dev, good defaults
Linting ESLint + typescript-eslint Use flat config
Formatting Prettier Or Biome for speed
Package manager pnpm Fast, disk efficient
Runtime validation Zod Infer TS types from schemas