---
name: react-patterns
version: 2.0.0
description: Comprehensive React 19 patterns expert covering Server Components, Actions, use() hook, useOptimistic, useFormStatus, useFormState, React Compiler, concurrent features, Suspense, and modern TypeScript development. Proactively use for any React development, component architecture, state management, performance optimization, or when implementing React 19's latest features.
language: typescript,javascript,tsx,jsx
framework: react
license: MIT
allowed-tools: Read, Write, Edit, Bash, Grep, Glob
tags: [react, react-19, typescript, javascript, jsx, tsx, hooks, server-components, actions, suspense, concurrent-rendering, react-compiler, use-optimistic, form-actions]
category: frontend
subcategories: [components, hooks, state-management, performance, server-components, forms, testing]
---
# React Development Patterns
Expert guide for building modern React 19 applications with new concurrent features, Server Components, Actions, and advanced patterns.
## When to Use
- Building React 19 components with TypeScript/JavaScript
- Managing component state with useState and useReducer
- Handling side effects with useEffect
- Optimizing performance with useMemo and useCallback
- Creating custom hooks for reusable logic
- Implementing component composition patterns
- Working with refs using useRef
- Using React 19's new features (use(), useOptimistic, useFormStatus)
- Implementing Server Components and Actions
- Working with Suspense and concurrent rendering
- Building forms with new form hooks
## Core Hooks Patterns
### useState - State Management
Basic state declaration and updates:
```typescript
import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
);
}
```
State with initializer function (expensive computation):
```typescript
const [state, setState] = useState(() => {
const initialState = computeExpensiveValue();
return initialState;
});
```
Multiple state variables:
```typescript
function UserProfile() {
const [name, setName] = useState('');
const [age, setAge] = useState(0);
const [email, setEmail] = useState('');
return (
);
}
```
### Lists and Keys
```typescript
function UserList({ users }: { users: User[] }) {
return (
{users.map(user => (
{user.name}
))}
);
}
```
## Best Practices
### General React Best Practices
1. **Dependency Arrays**: Always specify correct dependencies in useEffect
2. **State Structure**: Keep state minimal and avoid redundant state
3. **Component Size**: Keep components small and focused
4. **Custom Hooks**: Extract complex logic into reusable custom hooks
5. **TypeScript**: Use TypeScript for type safety
6. **Keys**: Use stable IDs as keys for list items, not array indices
7. **Immutability**: Never mutate state directly
8. **Effects**: Use effects only for synchronization with external systems
9. **Performance**: Profile before optimizing with useMemo/useCallback
### React 19 Specific Best Practices
1. **Server Components**: Use Server Components for data fetching and static content
2. **Client Components**: Mark components as 'use client' only when necessary
3. **Actions**: Use Server Actions for mutations and form submissions
4. **Optimistic Updates**: Implement useOptimistic for better UX
5. **use() Hook**: Use for reading promises and context conditionally
6. **Form State**: Use useFormState and useFormStatus for complex forms
7. **Concurrent Features**: Leverage useTransition for non-urgent updates
8. **Error Boundaries**: Implement proper error handling with error boundaries
## Common Pitfalls
### General React Pitfalls
❌ **Missing Dependencies**:
```typescript
useEffect(() => {
// Uses 'count' but doesn't include it in deps
console.log(count);
}, []); // Wrong!
```
❌ **Mutating State**:
```typescript
const [items, setItems] = useState([]);
items.push(newItem); // Wrong! Mutates state
setItems(items); // Won't trigger re-render
```
✅ **Correct Approach**:
```typescript
setItems([...items, newItem]); // Create new array
```
### React 19 Specific Pitfalls
❌ **Using use() outside of render**:
```typescript
// Wrong!
function handleClick() {
const data = use(promise); // Error: use() can only be called in render
}
```
✅ **Correct usage**:
```tsx
function Component({ promise }) {
const data = use(promise); // Correct: called during render
return
{data}
;
}
```
❌ **Forgetting 'use server' directive**:
```typescript
// Wrong - missing 'use server'
export async function myAction() {
// This will run on the client!
}
```
✅ **Correct Server Action**:
```typescript
'use server'; // Must be at the top
export async function myAction() {
// Now runs on the server
}
```
❌ **Mixing Server and Client logic incorrectly**:
```tsx
// Wrong - trying to use browser APIs in Server Component
export default async function ServerComponent() {
const width = window.innerWidth; // Error: window is not defined
return
{width}
;
}
```
✅ **Correct separation**:
```tsx
// Server Component for data
export default async function ServerComponent() {
const data = await fetchData();
return ;
}
// Client Component for browser APIs
'use client';
function ClientComponent({ data }) {
const [width, setWidth] = useState(window.innerWidth);
// Handle resize logic...
return
{width}
;
}
```
## React 19 New Features
### use() Hook - Reading Resources
The `use()` hook reads the value from a resource like a Promise or Context:
```typescript
import { use } from 'react';
// Reading a Promise in a component
function MessageComponent({ messagePromise }) {
const message = use(messagePromise);
return
{message}
;
}
// Reading Context conditionally
function Button() {
if (condition) {
const theme = use(ThemeContext);
return ;
}
return ;
}
```
### useOptimistic Hook - Optimistic UI Updates
Manage optimistic UI updates for async operations:
```typescript
import { useOptimistic } from 'react';
function TodoList({ todos, addTodo }) {
const [optimisticTodos, addOptimisticTodo] = useOptimistic(
todos,
(state, newTodo) => [...state, newTodo]
);
const handleSubmit = async (formData) => {
const newTodo = { id: Date.now(), text: formData.get('text') };
// Optimistically add to UI
addOptimisticTodo(newTodo);
// Actually add to backend
await addTodo(newTodo);
};
return (
);
}
```
### useFormStatus Hook - Form State
Access form submission status from child components:
```typescript
import { useFormStatus } from 'react';
function SubmitButton() {
const { pending, data } = useFormStatus();
return (
);
}
function ContactForm() {
return (
);
}
```
### useFormState Hook - Form State Management
Manage form state with error handling:
```typescript
import { useFormState } from 'react';
async function submitAction(prevState: string | null, formData: FormData) {
const email = formData.get('email') as string;
if (!email.includes('@')) {
return 'Invalid email address';
}
await submitToDatabase(email);
return null;
}
function EmailForm() {
const [state, formAction] = useFormState(submitAction, null);
return (
);
}
```
### Server Actions
Define server-side functions for form handling:
```typescript
// app/actions.ts
'use server';
import { redirect } from 'next/navigation';
import { revalidatePath } from 'next/cache';
export async function createPost(formData: FormData) {
const title = formData.get('title') as string;
const content = formData.get('content') as string;
// Validate input
if (!title || !content) {
return { error: 'Title and content are required' };
}
// Save to database
const post = await db.post.create({
data: { title, content }
});
// Update cache and redirect
revalidatePath('/posts');
redirect(`/posts/${post.id}`);
}
```
### Server Components
Components that run exclusively on the server:
```typescript
// app/posts/page.tsx - Server Component
async function PostsPage() {
// Server-side data fetching
const posts = await db.post.findMany({
orderBy: { createdAt: 'desc' },
take: 10
});
return (
);
}
```
### Server Components Best Practices
1. **Keep Server Components Server-Only**: No event handlers, hooks, or browser APIs
2. **Minimize Client Components**: Only use 'use client' when necessary
3. **Pass Data as Props**: Serialize data when passing from Server to Client
4. **Use Server Actions for Mutations**: Keep data operations on the server
```typescript
// Good: Server Component for static content
async function ProductPage({ id }: { id: string }) {
const product = await fetchProduct(id);
return (
{product.name}
{product.description}
);
}
// Client Component only for interactivity
'use client';
function AddToCartForm({ productId }: { productId: string }) {
const [isAdding, setIsAdding] = useState(false);
async function handleSubmit() {
setIsAdding(true);
await addToCart(productId);
setIsAdding(false);
}
return (
);
}
```
## Migration Guide
### From React 18 to 19
1. **Update Dependencies**:
```bash
npm install react@19 react-dom@19
```
2. **Adopt Server Components**:
- Identify data-fetching components
- Remove client-side code from Server Components
- Add 'use client' directive where needed
3. **Replace Manual Optimistic Updates**:
```typescript
// Before
function TodoList({ todos, addTodo }) {
const [optimisticTodos, setOptimisticTodos] = useState(todos);
const handleAdd = async (text) => {
const newTodo = { id: Date.now(), text };
setOptimisticTodos([...optimisticTodos, newTodo]);
await addTodo(newTodo);
};
}
// After
function TodoList({ todos, addTodo }) {
const [optimisticTodos, addOptimisticTodo] = useOptimistic(
todos,
(state, newTodo) => [...state, newTodo]
);
const handleAdd = async (formData) => {
const newTodo = { id: Date.now(), text: formData.get('text') };
addOptimisticTodo(newTodo);
await addTodo(newTodo);
};
}
```
4. **Enable React Compiler**:
- Install babel-plugin-react-compiler
- Remove manual memoization
- Let the compiler optimize automatically
## References
- React 19 Official Docs: https://react.dev/blog/2024/04/25/react-19
- React Server Components: https://react.dev/reference/rsc/server-components
- React Compiler: https://react.dev/learn/react-compiler
- TypeScript with React: https://react-typescript-cheatsheet.netlify.app/