All React templates

React Component Architecture

Composition, prop design, and folder layout for scalable React codebases.

DevZone Tools1,860 copiesUpdated Mar 22, 2026ReactTypeScript
# CLAUDE.md — React Component Architecture

## Component types

- **UI primitives** — `<Button>`, `<Input>`, `<Card>`. Live in `components/ui/`. No app logic, no data fetching, no domain knowledge.
- **Feature components** — `<UserProfile>`, `<InvoiceList>`. Live in `features/<feature>/`. Compose primitives, own feature logic.
- **Layouts / providers** — `<AppLayout>`, `<ThemeProvider>`. Live in `app/` or `layouts/`. Mostly structural.

## Composition over configuration

- Prefer `children` and slot props over a long flat prop list. A component with 12 props is asking to be split.
- Compound components for related parts: `<Tabs>`, `<Tabs.List>`, `<Tabs.Trigger>`, `<Tabs.Panel>`. Share state via context internal to the parent.
- Render-props or hook patterns when the consumer needs to customize the rendering, not just the data.

## Prop design

- Required props first, optional props after.
- Boolean props default to `false`. Naming is positive: `disabled`, not `notDisabled`.
- Avoid `is*` and `has*` for the same concept. Pick one (`isLoading`, `hasError`).
- Use discriminated unions for mutually exclusive prop sets (`{ kind: 'text', value } | { kind: 'icon', icon }`).
- Spread the rest of native HTML props (`...rest`) to the underlying element so consumers can pass `aria-*`, `data-*`, etc.

## Folder layout

```
features/users/
  components/
    UserCard.tsx
    UserAvatar.tsx
  hooks/
    useUser.ts
  api.ts
  types.ts
  index.ts        // public surface
```

- The `index.ts` is the only file other features should import from.
- Internal files importing each other use relative paths; cross-feature imports use the alias (`@/features/users`).

## Splitting components

- Split when:
  - The component has more than one reason to change
  - State and rendering are independent
  - You'd want to test parts separately
- Don't split for line count alone. A 200-line cohesive component beats four 50-line confused ones.

## Performance

- Memoize at boundaries (`React.memo`) only after profiling. Most components don't need it.
- Big lists: use `react-window` or `@tanstack/react-virtual` instead of rendering thousands of nodes.
- Code-split at the route level with `React.lazy`. Don't lazy-load primitives.

## Don't

- Don't pass JSX as a prop just to "skip" rendering — use `<Suspense>` or conditional rendering.
- Don't barrel-export every component from `components/index.ts`. Big barrels break tree-shaking.
- Don't put feature logic into UI primitives. The primitive should work in any app.
- Don't reach into a child's internals via refs. If you need to, redesign the API.

Other React templates