@@ -16,6 +16,7 @@ import type {
1616 RSCPayload ,
1717 RSCRouteManifest ,
1818 RSCRenderPayload ,
19+ RSCRedirectPayload ,
1920} from "./server.rsc" ;
2021import type {
2122 DataStrategyFunction ,
@@ -63,16 +64,20 @@ type WindowWithRouterGlobals = Window &
6364 __routerActionID : number ;
6465 } ;
6566
67+ const startTransition = React . startTransition as (
68+ cb : ( ) => Promise < void > | void ,
69+ ) => void ;
70+
6671const patchRoutes = ( ...args : Parameters < DataRouter [ "patchRoutes" ] > ) => {
67- React . startTransition ( ( ) => {
72+ startTransition ( ( ) => {
6873 ( window as WindowWithRouterGlobals ) . __reactRouterDataRouter . patchRoutes (
6974 ...args ,
7075 ) ;
7176 } ) ;
7277} ;
7378
7479const navigate = ( ...args : Parameters < DataRouter [ "navigate" ] > ) => {
75- React . startTransition ( ( ) => {
80+ startTransition ( ( ) => {
7681 ( window as WindowWithRouterGlobals ) . __reactRouterDataRouter . navigate (
7782 ...args ,
7883 ) ;
@@ -84,7 +89,7 @@ const internalSetStateDoNotUseOrYouWillBreakYourApp = (
8489 DataRouter [ "_internalSetStateDoNotUseOrYouWillBreakYourApp" ]
8590 >
8691) => {
87- React . startTransition ( ( ) => {
92+ startTransition ( ( ) => {
8893 (
8994 window as WindowWithRouterGlobals
9095 ) . __reactRouterDataRouter . _internalSetStateDoNotUseOrYouWillBreakYourApp (
@@ -96,7 +101,7 @@ const internalSetStateDoNotUseOrYouWillBreakYourApp = (
96101const internalSetRoutes = (
97102 ...args : Parameters < DataRouter [ "_internalSetRoutes" ] >
98103) => {
99- React . startTransition ( ( ) => {
104+ startTransition ( ( ) => {
100105 (
101106 window as WindowWithRouterGlobals
102107 ) . __reactRouterDataRouter . _internalSetRoutes ( ...args ) ;
@@ -153,105 +158,109 @@ export function createCallServer({
153158 const globalVar = window as WindowWithRouterGlobals ;
154159
155160 let landedActionId = 0 ;
156- return async ( id : string , args : unknown [ ] ) => {
161+ return async function callServer ( id : string , args : unknown [ ] ) {
157162 let actionId = ( globalVar . __routerActionID =
158163 ( globalVar . __routerActionID ??= 0 ) + 1 ) ;
159164
160165 const temporaryReferences = createTemporaryReferenceSet ( ) ;
161- const payloadPromise = fetchImplementation (
166+ const encoded = await encodeReply ( args , { temporaryReferences } ) ;
167+
168+ const response = await fetchImplementation (
162169 new Request ( location . href , {
163- body : await encodeReply ( args , { temporaryReferences } ) ,
170+ body : encoded ,
164171 method : "POST" ,
165172 headers : {
166173 Accept : "text/x-component" ,
167174 "rsc-action-id" : id ,
168175 } ,
169176 } ) ,
170- ) . then ( ( response ) => {
171- if ( ! response . body ) {
172- throw new Error ( "No response body" ) ;
173- }
174- return createFromReadableStream ( response . body , {
175- temporaryReferences,
176- } ) as Promise < RSCPayload > ;
177- } ) ;
177+ ) ;
178178
179- ( React . startTransition as ( cb : ( ) => void | Promise < void > ) => void ) ( ( ) =>
180- Promise . resolve ( payloadPromise )
181- . then ( async ( payload ) => {
182- if ( payload . type === "redirect" ) {
183- if ( payload . reload || isExternalLocation ( payload . location ) ) {
184- window . location . href = payload . location ;
185- return ;
186- }
187-
188- React . startTransition ( ( ) => {
189- navigate ( payload . location , {
190- replace : payload . replace ,
191- } ) ;
192- } ) ;
193- return ;
194- }
179+ if ( ! response . body ) {
180+ throw new Error ( "No response body" ) ;
181+ }
195182
196- if ( payload . type !== "action" ) {
197- throw new Error ( "Unexpected payload type" ) ;
183+ const payload = ( await Promise . resolve (
184+ createFromReadableStream ( response . body , {
185+ temporaryReferences,
186+ } ) ,
187+ ) ) as RSCPayload ;
188+
189+ let redirect : RSCRedirectPayload | undefined ;
190+ let rerender : RSCRenderPayload | undefined ;
191+ let actionResult : unknown ;
192+
193+ switch ( payload . type ) {
194+ case "action" : {
195+ actionResult = payload . actionResult ;
196+ let rerenderPayload = await payload . rerender ;
197+ switch ( rerenderPayload ?. type ) {
198+ case "redirect" : {
199+ redirect = rerenderPayload ;
200+ break ;
198201 }
199-
200- const rerender = await payload . rerender ;
201- if (
202- rerender &&
203- landedActionId < actionId &&
204- globalVar . __routerActionID <= actionId
205- ) {
206- if ( rerender . type === "redirect" ) {
207- if ( rerender . reload || isExternalLocation ( rerender . location ) ) {
208- window . location . href = rerender . location ;
209- return ;
210- }
211- React . startTransition ( ( ) => {
212- navigate ( rerender . location , {
213- replace : rerender . replace ,
214- } ) ;
215- } ) ;
216- return ;
217- }
218-
219- let lastMatch : RSCRouteManifest | undefined ;
220- for ( const match of rerender . matches ) {
221- patchRoutes (
222- lastMatch ?. id ?? null ,
223- [ createRouteFromServerManifest ( match ) ] ,
224- true ,
225- ) ;
226- lastMatch = match ;
227- }
228-
229- internalSetStateDoNotUseOrYouWillBreakYourApp ( {
230- loaderData : Object . assign (
231- { } ,
232- globalVar . __reactRouterDataRouter . state . loaderData ,
233- rerender . loaderData ,
234- ) ,
235- errors : rerender . errors
236- ? Object . assign (
237- { } ,
238- globalVar . __reactRouterDataRouter . state . errors ,
239- rerender . errors ,
240- )
241- : null ,
242- } ) ;
202+ case "render" : {
203+ rerender = rerenderPayload ;
243204 }
244- } )
245- . catch ( ( ) => { } ) ,
246- ) ;
205+ }
206+ break ;
207+ }
208+ case "redirect" : {
209+ actionResult = payload . actionResult ;
210+ redirect = payload ;
211+ break ;
212+ }
213+ case "render" : {
214+ rerender = payload ;
215+ break ;
216+ }
217+ }
247218
248- return payloadPromise . then ( ( payload ) => {
249- if ( payload . type !== "action" && payload . type !== "redirect" ) {
250- throw new Error ( "Unexpected payload type" ) ;
219+ startTransition ( ( ) => {
220+ if ( redirect ) {
221+ if ( redirect . reload || isExternalLocation ( redirect . location ) ) {
222+ window . location . href = redirect . location ;
223+ return ;
224+ }
225+
226+ navigate ( redirect . location , {
227+ replace : redirect . replace ,
228+ } ) ;
229+ return ;
251230 }
231+ if (
232+ rerender &&
233+ landedActionId < actionId &&
234+ globalVar . __routerActionID <= actionId
235+ ) {
236+ let lastMatch : RSCRouteManifest | undefined ;
237+ for ( const match of rerender . matches ) {
238+ patchRoutes (
239+ lastMatch ?. id ?? null ,
240+ [ createRouteFromServerManifest ( match ) ] ,
241+ true ,
242+ ) ;
243+ lastMatch = match ;
244+ }
252245
253- return payload . actionResult ;
246+ internalSetStateDoNotUseOrYouWillBreakYourApp ( {
247+ loaderData : Object . assign (
248+ { } ,
249+ globalVar . __reactRouterDataRouter . state . loaderData ,
250+ rerender . loaderData ,
251+ ) ,
252+ errors : rerender . errors
253+ ? Object . assign (
254+ { } ,
255+ globalVar . __reactRouterDataRouter . state . errors ,
256+ rerender . errors ,
257+ )
258+ : null ,
259+ } ) ;
260+ }
254261 } ) ;
262+
263+ return actionResult ;
255264 } ;
256265}
257266
0 commit comments