# Component Anatomy

> The consistent internal structure every component follows — imports, types, constants, function, export.

**Principle:** When every component follows the same structure, you stop thinking about where things go inside a file and start thinking about what the component actually does. Consistent anatomy means anyone on the team can open any file and immediately know where to look — props are always at the top, constants are always before the function, exports are always at the bottom.

**Tip:** The hardest part of component anatomy is constants vs. props. Rule of thumb: if it never changes based on what's passed in, it is a constant. If it could change from outside, it is a prop.

**Rules:**
- **Imports first** — Order: React → external libraries → internal aliases (@/) → relative imports (./). This makes dependencies visible at a glance.
- **Types and interfaces second** — Define all types used in this file immediately after imports. Props interface always comes first.
- **Constants third** — Component-scoped constants (static data, config, labels) come before the function. Never define constants inside the function body.
- **Component function fourth** — The function itself comes after everything it depends on. Keep it focused — if it grows past 200 lines, split it.
- **Named export last** — Always use named exports, never default exports. Named exports make refactoring and search easier.

**Pattern** — `components/RecipeCard.tsx — anatomy template`

```
// 1. IMPORTS — React → external → internal → relative
import { useState } from 'react';
import Link from 'next/link';
import { cn } from '@/shared/utils/cn';
import { useSavedStore } from '../stores/useSavedStore';

// 2. TYPES
interface RecipeCardProps {
  slug: string;
  title: string;
  description: string;
  category: string;
}

// 3. CONSTANTS — static, never changes based on props
const MAX_DESCRIPTION_LENGTH = 120;
const CARD_BASE_CLASS = 'rounded-xl border bg-white shadow-sm';

// 4. COMPONENT FUNCTION
export function RecipeCard({ slug, title, description, category }: RecipeCardProps) {
  const [isHovered, setIsHovered] = useState(false);
  const { isSaved } = useSavedStore();

  const truncated = description.slice(0, MAX_DESCRIPTION_LENGTH);

  return (
    <div className={cn(CARD_BASE_CLASS, isHovered && 'shadow-lg')}>
      {/* ... */}
    </div>
  );
}

// 5. EXPORT — named, at the bottom
// (already exported above with "export function")
```

**Implementation — Next.js**

In Next.js, mark client components explicitly with 'use client' — it goes above all imports as the very first line. See the annotated Button component in the starter template: github.com/sindev08/react-principles-nextjs → src/ui/Button.tsx

File: `ui/Button.tsx — from react-principles-nextjs starter`

```
// 'use client' goes ABOVE imports if the component is a Client Component
// (Button doesn't need it — no hooks or browser APIs)

// 1. IMPORTS — React → external → internal (@/) → relative (./)
import { type ButtonHTMLAttributes } from 'react';
import { cn } from '@/shared/utils';

// 2. TYPES — props interface first, then supporting types
interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
  variant?: ButtonVariant;
  size?: ButtonSize;
}
type ButtonVariant = 'primary' | 'secondary' | 'outline' | 'ghost' | 'danger';
type ButtonSize = 'sm' | 'md' | 'lg';

// 3. CONSTANTS — static, never changes based on props
const VARIANT_CLASSES: Record<ButtonVariant, string> = {
  primary: 'bg-zinc-900 text-white hover:bg-zinc-800 ...',
  secondary: 'bg-zinc-100 text-zinc-900 hover:bg-zinc-200 ...',
  // ...
};
const SIZE_CLASSES: Record<ButtonSize, string> = {
  sm: 'h-8 px-3 text-xs',
  md: 'h-10 px-4 text-sm',
  lg: 'h-12 px-6 text-base',
};

// 4. COMPONENT — named export, never default
export function Button({ variant = 'primary', size = 'md', className, children, ...props }: ButtonProps) {
  return (
    <button className={cn(BASE_CLASSES, VARIANT_CLASSES[variant], SIZE_CLASSES[size], className)} {...props}>
      {children}
    </button>
  );
}
```

**Implementation — Vite**

In Vite + React, all components are client-side by default. No 'use client' needed — just follow the anatomy.

File: `features/cookbook/components/RecipeCard.tsx`

```tsx
// 1. IMPORTS
import { useState } from 'react';
import { Link } from 'react-router-dom';
import { cn } from '@/shared/utils/cn';

// 2. TYPES
interface RecipeCardProps {
  slug: string;
  title: string;
}

// 3. CONSTANTS
const BASE_PATH = '/cookbook';

// 4. COMPONENT
export function RecipeCard({ slug, title }: RecipeCardProps) {
  const [saved, setSaved] = useState(false);

  return (
    <Link to={`${BASE_PATH}/${slug}`}>
      <span>{title}</span>
    </Link>
  );
}
```

Read more: https://reactprinciples.dev/cookbook/component-anatomy

---

Source: https://reactprinciples.dev/nextjs/cookbook/component-anatomy
All recipes (compact): https://reactprinciples.dev/llms.txt
All recipes (full): https://reactprinciples.dev/llms-full.txt
