Skip to content

Improve error messages when interactive component is missing 'use client' with RSC enabled #2394

@ihabadham

Description

@ihabadham

Problem

When RSC is enabled (enable_rsc_support = true), the packs generator classifies any component without 'use client' as a server component and registers it via registerServerComponent(). If an interactive component (using hooks, class components, etc.) is missing 'use client', it crashes at runtime with vague error messages that don't point to the actual problem.

Error messages users see

Depending on the component type and failure path, users get one of these:

  1. TypeError: require is not a function — ExecJS fallback after Node renderer crashes. This is the error shown in the browser/Rails logs. Completely unrelated to the actual cause.

  2. Rails context does not have server side RSC payload parameters — Only visible in the Node renderer log file. The guidance says "ensure enable_rsc_support = true" which is already set. Never mentions 'use client'.

  3. Class extends value undefined is not a constructor or null — For class-based components. No indication of what to do.

None of these tell the user: "Your component uses client-side features but is missing the 'use client' directive."

How Next.js handles this

Next.js gives a clear build-time error:

"You're importing a component that needs useState. It only works in a Client Component but none of its parents are marked with "use client", so they're Server Components by default."

This tells you what's wrong, why, and how to fix it.

Reproduction (Pro dummy app)

  1. Remove 'use client' from react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/HelloWorld.jsx
  2. Run bundle exec rake react_on_rails:generate_packs — HelloWorld moves from ReactOnRails.register() to registerServerComponent()
  3. Build webpack, start the Node renderer and Rails server
  4. Visit /server_side_hello_world — crashes with Class extends value undefined is not a constructor or null

The root cause: packs_generator.rb (line 135) uses client_entrypoint? to check for 'use client'. Without the directive, any interactive component gets wrapped by wrapServerComponentRenderer, which expects RSC streaming context that doesn't exist for regular SSR renders.

Suggested improvements

  1. Build-time detection: The RSCWebpackPlugin or packs generator could detect when a component registered via registerServerComponent uses client-only APIs (hooks, class components, event handlers) and warn at build time.

  2. Better runtime error message: The assertRailsContextWithServerStreamingCapabilities error could mention 'use client' as a possible cause:

    "If this component uses hooks, event handlers, or other client-side features, add 'use client' at the top of the file."

  3. Documentation/tips: When RSC is enabled, warn users that existing interactive components need 'use client' at the top of the file. Without it, they'll be treated as server components and may crash at runtime.

Related

Discovered during work on PR #2284.

Metadata

Metadata

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions