Skip to content

Commit 7ad6d79

Browse files
committed
[react-ssr-prepass] Fix not resolving client components
Change-Id: I127288025c76a12685ead339200396c0a14acb93
1 parent 5fd49be commit 7ad6d79

File tree

3 files changed

+61
-13
lines changed

3 files changed

+61
-13
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@plasmicapp/react-ssr-prepass",
3-
"version": "2.0.5",
3+
"version": "2.0.6",
44
"description": "A custom partial React SSR renderer for prefetching and suspense",
55
"main": "dist/react-ssr-prepass.js",
66
"module": "dist/react-ssr-prepass.es.js",

src/__tests__/visitor.test.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ import {
2929

3030
import { visitElement } from '../visitor'
3131

32+
import { REACT_ELEMENT_TYPE, REACT_LAZY_TYPE } from '../symbols'
33+
3234
const { ReactCurrentDispatcher } = (React: any)
3335
.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED
3436

@@ -159,6 +161,35 @@ describe('visitElement', () => {
159161
})
160162
})
161163

164+
it('resolves lazy components of resolved modules', () => {
165+
const ClientComponent = jest.fn().mockReturnValue(null)
166+
const queue = []
167+
const children = visitElement(
168+
{
169+
$$typeof: REACT_ELEMENT_TYPE,
170+
props: {},
171+
key: null,
172+
ref: null,
173+
type: {
174+
$$typeof: REACT_LAZY_TYPE,
175+
_payload: {
176+
reason: null,
177+
status: 'resolved_module',
178+
_response: {},
179+
_testComponent: ClientComponent
180+
},
181+
_init: (payload) => payload._testComponent
182+
}
183+
},
184+
queue,
185+
() => {}
186+
)
187+
188+
expect(children.length).toBe(1)
189+
expect(queue.length).toBe(0)
190+
expect(children[0].type).toBe(ClientComponent)
191+
})
192+
162193
it('walks over forwardRef components', () => {
163194
const Test = React.forwardRef(Noop)
164195
const children = visitElement(<Test />, [], () => {})

src/render/lazyComponent.js

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,20 @@ const resolve = (type: LazyComponent): Promise<void> => {
5555
}))
5656
}
5757

58+
const makeFrame = (
59+
type: LazyComponent,
60+
props: DefaultProps,
61+
thenable: Promise<any>
62+
) => ({
63+
kind: 'frame.lazy',
64+
contextMap: getCurrentContextMap(),
65+
contextStore: getCurrentContextStore(),
66+
errorFrame: getCurrentErrorFrame(),
67+
thenable,
68+
props,
69+
type
70+
})
71+
5872
const render = (
5973
type: LazyComponent,
6074
props: DefaultProps,
@@ -63,11 +77,18 @@ const render = (
6377
// Component has previously been fetched successfully,
6478
// so create the element with passed props and return it
6579
const payload = ((type._payload || type: any): LazyComponentPayload)
66-
if (payload._status === 1) {
80+
if (payload._status === 1 && payload._result) {
6781
return createElement(payload._result, props)
6882
}
6983

70-
return null
84+
try {
85+
return createElement((type: any)._init((type: any)._payload), props)
86+
} catch (err) {
87+
if (!!err && typeof err.then === 'function') {
88+
queue.push(makeFrame(type, props, err))
89+
}
90+
return null
91+
}
7192
}
7293

7394
export const mount = (
@@ -77,16 +98,12 @@ export const mount = (
7798
): Node => {
7899
// If the component has not been fetched yet, suspend this component
79100
const payload = ((type._payload || type: any): LazyComponentPayload)
80-
if (payload._status <= 0) {
81-
queue.push({
82-
kind: 'frame.lazy',
83-
contextMap: getCurrentContextMap(),
84-
contextStore: getCurrentContextStore(),
85-
errorFrame: getCurrentErrorFrame(),
86-
thenable: resolve(type),
87-
props,
88-
type
89-
})
101+
// For lazy components from resolved modules (e.g. Client Components)
102+
// The `payload._status` is null.
103+
// Reference code for "normal" lazy components: https://github.com/facebook/react/blob/main/packages/react/src/ReactLazy.js#L53
104+
// Reference code for Client Component chunks: https://github.com/facebook/react/blob/main/packages/react-client/src/ReactFlightClient.js#L955
105+
if (payload._status != null && payload._status <= 0) {
106+
queue.push(makeFrame(type, props, resolve(type)))
90107

91108
return null
92109
}

0 commit comments

Comments
 (0)