Claude
Skills
Sign in
Back

frontend-patterns

Included with Lifetime
$97 forever

Modern frontend architecture patterns for React, Next.js, and TypeScript including component composition, state management, performance optimization, accessibility, and responsive design. Use when building UI components, implementing frontend features, optimizing performance, or working with React/Next.js applications.

Design

What this skill does


# Frontend Development Patterns

This skill provides comprehensive guidance for modern frontend development using React, Next.js, TypeScript, and related technologies.

## Component Architecture

### Component Composition Patterns

**Container/Presentational Pattern**:
```typescript
// Presentational component (pure, reusable)
interface UserCardProps {
  name: string;
  email: string;
  avatar: string;
  onEdit: () => void;
}

function UserCard({ name, email, avatar, onEdit }: UserCardProps) {
  return (
    <div className="user-card">
      <img src={avatar} alt={name} />
      <h3>{name}</h3>
      <p>{email}</p>
      <button onClick={onEdit}>Edit</button>
    </div>
  );
}

// Container component (handles logic, state, data fetching)
function UserCardContainer({ userId }: { userId: string }) {
  const { data: user, isLoading } = useUser(userId);
  const { mutate: updateUser } = useUpdateUser();

  if (isLoading) return <Skeleton />;
  if (!user) return <NotFound />;

  return <UserCard {...user} onEdit={() => updateUser(user.id)} />;
}
```

**Compound Components Pattern**:
```typescript
// Flexible, composable API
<Tabs defaultValue="profile">
  <TabsList>
    <TabsTrigger value="profile">Profile</TabsTrigger>
    <TabsTrigger value="settings">Settings</TabsTrigger>
  </TabsList>
  <TabsContent value="profile">
    <ProfileForm />
  </TabsContent>
  <TabsContent value="settings">
    <SettingsForm />
  </TabsContent>
</Tabs>
```

### Component Organization

```
components/
├── ui/                    # Primitive components (buttons, inputs)
│   ├── button.tsx
│   ├── input.tsx
│   └── card.tsx
├── forms/                 # Form components
│   ├── login-form.tsx
│   └── register-form.tsx
├── features/              # Feature-specific components
│   ├── user-profile/
│   │   ├── profile-header.tsx
│   │   ├── profile-stats.tsx
│   │   └── index.ts
│   └── dashboard/
│       ├── dashboard-grid.tsx
│       └── dashboard-card.tsx
└── layouts/               # Layout components
    ├── main-layout.tsx
    └── auth-layout.tsx
```

## State Management

### Local State (useState)

Use for:
- Component-specific UI state
- Form inputs
- Toggles, modals

```typescript
function SearchBar() {
  const [query, setQuery] = useState('');
  const [isOpen, setIsOpen] = useState(false);

  return (
    <div>
      <input
        value={query}
        onChange={(e) => setQuery(e.target.value)}
      />
      {isOpen && <SearchResults query={query} />}
    </div>
  );
}
```

### Global State (Zustand)

Use for:
- User authentication state
- Theme preferences
- Shopping cart
- Cross-component shared state

```typescript
import create from 'zustand';

interface UserStore {
  user: User | null;
  setUser: (user: User) => void;
  logout: () => void;
}

export const useUserStore = create<UserStore>((set) => ({
  user: null,
  setUser: (user) => set({ user }),
  logout: () => set({ user: null }),
}));

// Usage
function Header() {
  const user = useUserStore((state) => state.user);
  const logout = useUserStore((state) => state.logout);

  return <div>{user ? user.name : 'Guest'}</div>;
}
```

### Server State (React Query / TanStack Query)

Use for:
- API data fetching
- Caching API responses
- Optimistic updates
- Background refetching

```typescript
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';

// Fetch data
function UserProfile({ userId }: { userId: string }) {
  const { data, isLoading, error } = useQuery({
    queryKey: ['user', userId],
    queryFn: () => fetchUser(userId),
    staleTime: 5 * 60 * 1000, // 5 minutes
  });

  if (isLoading) return <Skeleton />;
  if (error) return <Error error={error} />;

  return <div>{data.name}</div>;
}

// Mutations with optimistic updates
function useUpdateUser() {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: (user: User) => api.updateUser(user),
    onMutate: async (newUser) => {
      // Cancel outgoing refetches
      await queryClient.cancelQueries({ queryKey: ['user', newUser.id] });

      // Snapshot previous value
      const previous = queryClient.getQueryData(['user', newUser.id]);

      // Optimistically update
      queryClient.setQueryData(['user', newUser.id], newUser);

      return { previous };
    },
    onError: (err, newUser, context) => {
      // Rollback on error
      queryClient.setQueryData(['user', newUser.id], context?.previous);
    },
    onSettled: (newUser) => {
      // Refetch after mutation
      queryClient.invalidateQueries({ queryKey: ['user', newUser.id] });
    },
  });
}
```

## Performance Optimization

### 1. Memoization

**useMemo** (expensive calculations):
```typescript
function ProductList({ products }: { products: Product[] }) {
  const sortedProducts = useMemo(
    () => products.sort((a, b) => b.price - a.price),
    [products]
  );

  return <div>{sortedProducts.map(...)}</div>;
}
```

**useCallback** (prevent re-renders):
```typescript
function Parent() {
  const [count, setCount] = useState(0);

  // ✅ Memoized - Child won't re-render unless count changes
  const handleClick = useCallback(() => {
    setCount(c => c + 1);
  }, []);

  return <Child onClick={handleClick} />;
}

const Child = memo(function Child({ onClick }: { onClick: () => void }) {
  console.log('Child rendered');
  return <button onClick={onClick}>Click</button>;
});
```

**React.memo** (prevent component re-renders):
```typescript
const ExpensiveComponent = memo(function ExpensiveComponent({ data }) {
  // Only re-renders if data changes
  return <div>{/* expensive rendering */}</div>;
});
```

### 2. Code Splitting

**Route-based splitting** (Next.js automatic):
```typescript
// app/dashboard/page.tsx - automatically code split
export default function DashboardPage() {
  return <Dashboard />;
}
```

**Component-level splitting**:
```typescript
import dynamic from 'next/dynamic';

const HeavyChart = dynamic(() => import('@/components/heavy-chart'), {
  loading: () => <Skeleton />,
  ssr: false, // Don't render on server
});

function Analytics() {
  return <HeavyChart data={chartData} />;
}
```

### 3. Image Optimization

```typescript
import Image from 'next/image';

// ✅ Optimized - Next.js Image component
<Image
  src="/hero.jpg"
  alt="Hero image"
  width={800}
  height={600}
  priority // Load immediately for LCP
  placeholder="blur"
  blurDataURL="data:image/..."
/>

// ❌ Not optimized
<img src="/hero.jpg" alt="Hero" />
```

### 4. Lazy Loading

```typescript
import { lazy, Suspense } from 'react';

const Comments = lazy(() => import('./comments'));

function Post() {
  return (
    <div>
      <PostContent />
      <Suspense fallback={<CommentsSkeleton />}>
        <Comments postId={postId} />
      </Suspense>
    </div>
  );
}
```

### 5. Virtual Scrolling

```typescript
import { useVirtualizer } from '@tanstack/react-virtual';

function VirtualList({ items }: { items: Item[] }) {
  const parentRef = useRef<HTMLDivElement>(null);

  const virtualizer = useVirtualizer({
    count: items.length,
    getScrollElement: () => parentRef.current,
    estimateSize: () => 50,
  });

  return (
    <div ref={parentRef} style={{ height: '400px', overflow: 'auto' }}>
      <div style={{ height: `${virtualizer.getTotalSize()}px` }}>
        {virtualizer.getVirtualItems().map((virtualRow) => (
          <div
            key={virtualRow.index}
            style={{
              position: 'absolute',
              top: 0,
              left: 0,
              width: '100%',
              height: `${virtualRow.size}px`,
              transform: `translateY(${virtualRow.start}px)`,
            }}
          >
            {items[virtualRow.index].name}
          </div>
        ))}
      </div>
    </div>
  );
}
```

## Accessibility (a11y)

### Semantic HTML

```typescript
// ✅ Semantic
<nav>
  <ul>
    <li><a href="/home">Home</a></li>
    <li><a href="/about">About</a></li>
  </ul>
</nav>

// ❌ Non-semantic
<div>
  <div>
    <div onClick={goHome}>Hom

Related in Design