Skip to content

Commit c1a8229

Browse files
justin808claude
andcommitted
Fix React 19 server bundle errors by using named imports instead of namespace imports
The issue was that with esModuleInterop: false in tsconfig.json, TypeScript was compiling `import * as React from 'react'` to `import ReactClient from 'react/index.js'`, which tried to access a default export that doesn't exist in React. This caused webpack to fail when bundling the server bundle with errors: - export 'createContext' was not found in 'react' - export 'useContext' was not found in 'react' - export 'Component' was not found in 'react' The fix is to use named imports directly: - `import { createContext, useContext, type ReactNode } from 'react'` - `import { Component, use, type ReactNode } from 'react'` This generates correct ES module imports that work with React 19's export structure. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent 93daa83 commit c1a8229

File tree

2 files changed

+16
-16
lines changed

2 files changed

+16
-16
lines changed

packages/react-on-rails-pro/src/RSCProvider.tsx

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,17 @@
1414

1515
'use client';
1616

17-
import * as React from 'react';
17+
import { createContext, useContext, type ReactNode } from 'react';
1818
import type { ClientGetReactServerComponentProps } from './getReactServerComponent.client.ts';
1919
import { createRSCPayloadKey } from './utils.ts';
2020

2121
type RSCContextType = {
22-
getComponent: (componentName: string, componentProps: unknown) => Promise<React.ReactNode>;
22+
getComponent: (componentName: string, componentProps: unknown) => Promise<ReactNode>;
2323

24-
refetchComponent: (componentName: string, componentProps: unknown) => Promise<React.ReactNode>;
24+
refetchComponent: (componentName: string, componentProps: unknown) => Promise<ReactNode>;
2525
};
2626

27-
const RSCContext = React.createContext<RSCContextType | undefined>(undefined);
27+
const RSCContext = createContext<RSCContextType | undefined>(undefined);
2828

2929
/**
3030
* Creates a provider context for React Server Components.
@@ -48,9 +48,9 @@ const RSCContext = React.createContext<RSCContextType | undefined>(undefined);
4848
export const createRSCProvider = ({
4949
getServerComponent,
5050
}: {
51-
getServerComponent: (props: ClientGetReactServerComponentProps) => Promise<React.ReactNode>;
51+
getServerComponent: (props: ClientGetReactServerComponentProps) => Promise<ReactNode>;
5252
}) => {
53-
const fetchRSCPromises: Record<string, Promise<React.ReactNode>> = {};
53+
const fetchRSCPromises: Record<string, Promise<ReactNode>> = {};
5454

5555
const getComponent = (componentName: string, componentProps: unknown) => {
5656
const key = createRSCPayloadKey(componentName, componentProps);
@@ -76,7 +76,7 @@ export const createRSCProvider = ({
7676

7777
const contextValue = { getComponent, refetchComponent };
7878

79-
return ({ children }: { children: React.ReactNode }) => {
79+
return ({ children }: { children: ReactNode }) => {
8080
return <RSCContext.Provider value={contextValue}>{children}</RSCContext.Provider>;
8181
};
8282
};
@@ -101,7 +101,7 @@ export const createRSCProvider = ({
101101
* ```
102102
*/
103103
export const useRSC = () => {
104-
const context = React.useContext(RSCContext);
104+
const context = useContext(RSCContext);
105105
if (!context) {
106106
throw new Error('useRSC must be used within a RSCProvider');
107107
}

packages/react-on-rails-pro/src/RSCRoute.tsx

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,19 @@
1616

1717
'use client';
1818

19-
import * as React from 'react';
19+
import { Component, use, type ReactNode } from 'react';
2020
import { useRSC } from './RSCProvider.tsx';
2121
import { ServerComponentFetchError } from './ServerComponentFetchError.ts';
2222

2323
/**
2424
* Error boundary component for RSCRoute that adds server component name and props to the error
2525
* So, the parent ErrorBoundary can refetch the server component
2626
*/
27-
class RSCRouteErrorBoundary extends React.Component<
28-
{ children: React.ReactNode; componentName: string; componentProps: unknown },
27+
class RSCRouteErrorBoundary extends Component<
28+
{ children: ReactNode; componentName: string; componentProps: unknown },
2929
{ error: Error | null }
3030
> {
31-
constructor(props: { children: React.ReactNode; componentName: string; componentProps: unknown }) {
31+
constructor(props: { children: ReactNode; componentName: string; componentProps: unknown }) {
3232
super(props);
3333
this.state = { error: null };
3434
}
@@ -75,9 +75,9 @@ export type RSCRouteProps = {
7575
componentProps: unknown;
7676
};
7777

78-
const PromiseWrapper = ({ promise }: { promise: Promise<React.ReactNode> }) => {
79-
// React.use is available in React 18.3+
80-
const promiseResult = React.use(promise);
78+
const PromiseWrapper = ({ promise }: { promise: Promise<ReactNode> }) => {
79+
// use is available in React 18.3+
80+
const promiseResult = use(promise);
8181

8282
// In case that an error happened during the rendering of the RSC payload before the rendering of the component itself starts
8383
// RSC bundle will return an error object serialized inside the RSC payload
@@ -88,7 +88,7 @@ const PromiseWrapper = ({ promise }: { promise: Promise<React.ReactNode> }) => {
8888
return promiseResult;
8989
};
9090

91-
const RSCRoute = ({ componentName, componentProps }: RSCRouteProps): React.ReactNode => {
91+
const RSCRoute = ({ componentName, componentProps }: RSCRouteProps): ReactNode => {
9292
const { getComponent } = useRSC();
9393
const componentPromise = getComponent(componentName, componentProps);
9494
return (

0 commit comments

Comments
 (0)