Skip to content

RSC Compatibility

Cindy Zhang edited this page Jun 23, 2026 · 1 revision

RSC Compatibility

Decision: All Astryx components that use React hooks must include the 'use client' directive.

For related decisions, see:


Context

Astryx components use useContext to consume theme tokens at runtime (via ThemeContext). This means every themed component is inherently a client component in React Server Components (RSC) environments.

Without the 'use client' directive, consumers who import any Astryx component in a Server Component file get a confusing createContext / useState error. The fix isn't obvious — they have to trace the import graph to understand why their file needs to be a client component.

This friction was reported by a dogfooder: a schema file that imported Text and Badge for rendering got pulled into a Server Component via page.tsx, and the error pointed at createContext deep in Astryx internals.


Decision

Every file in packages/core/src/ that uses any React hook must have 'use client' as its first statement (after any leading comments).

Hooks that trigger this requirement:

  • useState, useEffect, useRef, useContext, useCallback, useMemo
  • useId, useReducer, useLayoutEffect, useTransition, useImperativeHandle
  • createContext (creates a context that requires client-side resolution)

Files that do NOT need the directive:

  • Pure re-export barrels (index.ts)
  • Type-only files
  • Utility functions with no hooks
  • Static components that use only forwardRef (no hooks)
  • StyleX style definitions (*.stylex.ts)

Placement

The directive goes after any file-level JSDoc comment, before imports:

/**
 * @file Button.tsx
 * ...
 */

'use client';

import {forwardRef, useContext} from 'react';

Industry Context

This matches the approach used by every major React design system:

Library Approach
Chakra UI All components are client components. 'use client' baked into the package.
MUI Runtime theme via context + Emotion. Everything is client.
Radix Client components for interactive primitives.
shadcn/ui rsc: true config flag adds 'use client' to generated components.

No major design system has solved server-renderable themed components yet.


Future: Server-Renderable Components

The pre-compiled CSS work (Distribution) could change this. If themes resolve at build time via CSS layers instead of runtime context, then:

  1. Components like Text, Badge, Divider become genuinely server-renderable
  2. Only interactive components (Dialog, DropdownMenu, etc.) would need 'use client'
  3. Removing 'use client' from a component is a non-breaking change (it expands where the component can be used)

Until then, the directive stays on everything that uses hooks.


Enforcement

New components should include 'use client' from the start if they use any hooks. The Component Authoring Guide template includes it.

Rule of thumb: If your component file imports anything from 'react' other than types and forwardRef, it needs 'use client'.

Clone this wiki locally