@@ -4,130 +4,131 @@ import {
44 setServerCallback ,
55 createTemporaryReferenceSet ,
66 encodeReply ,
7- } from ' @vitejs/plugin-rsc/browser'
8- import React from ' react'
9- import { hydrateRoot } from ' react-dom/client'
10- import { rscStream } from ' rsc-html-stream/client'
11- import type { RscPayload } from ' ./entry.rsc'
7+ } from " @vitejs/plugin-rsc/browser" ;
8+ import React from " react" ;
9+ import { hydrateRoot } from " react-dom/client" ;
10+ import { rscStream } from " rsc-html-stream/client" ;
11+ import type { RscPayload } from " ./entry.rsc" ;
1212
1313async function main ( ) {
1414 // stash `setPayload` function to trigger re-rendering
1515 // from outside of `BrowserRoot` component (e.g. server function call, navigation, hmr)
16- let setPayload : ( v : RscPayload ) => void
16+ let setPayload : ( v : RscPayload ) => void ;
1717
1818 // deserialize RSC stream back to React VDOM for CSR
1919 const initialPayload = await createFromReadableStream < RscPayload > (
2020 // initial RSC stream is injected in SSR stream as <script>...FLIGHT_DATA...</script>
21- rscStream ,
22- )
21+ rscStream
22+ ) ;
2323
2424 // browser root component to (re-)render RSC payload as state
2525 function BrowserRoot ( ) {
26- const [ payload , setPayload_ ] = React . useState ( initialPayload )
26+ const [ payload , setPayload_ ] = React . useState ( initialPayload ) ;
2727
2828 React . useEffect ( ( ) => {
29- setPayload = ( v ) => React . startTransition ( ( ) => setPayload_ ( v ) )
30- } , [ setPayload_ ] )
29+ setPayload = ( v ) => React . startTransition ( ( ) => setPayload_ ( v ) ) ;
30+ } , [ setPayload_ ] ) ;
3131
3232 // re-fetch/render on client side navigation
3333 React . useEffect ( ( ) => {
34- return listenNavigation ( ( ) => fetchRscPayload ( ) )
35- } , [ ] )
34+ return listenNavigation ( ( ) => fetchRscPayload ( ) ) ;
35+ } , [ ] ) ;
3636
37- return payload . root
37+ return payload . root ;
3838 }
3939
4040 // re-fetch RSC and trigger re-rendering
4141 async function fetchRscPayload ( ) {
4242 const payload = await createFromFetch < RscPayload > (
43- fetch ( window . location . href ) ,
44- )
45- setPayload ( payload )
43+ fetch ( globalThis . location . href )
44+ ) ;
45+ setPayload ( payload ) ;
4646 }
4747
4848 // register a handler which will be internally called by React
4949 // on server function request after hydration.
5050 setServerCallback ( async ( id , args ) => {
51- const url = new URL ( window . location . href )
52- const temporaryReferences = createTemporaryReferenceSet ( )
51+ const url = new URL ( globalThis . location . href ) ;
52+ const temporaryReferences = createTemporaryReferenceSet ( ) ;
5353 const payload = await createFromFetch < RscPayload > (
5454 fetch ( url , {
55- method : ' POST' ,
55+ method : " POST" ,
5656 body : await encodeReply ( args , { temporaryReferences } ) ,
5757 headers : {
58- ' x-rsc-action' : id ,
58+ " x-rsc-action" : id ,
5959 } ,
6060 } ) ,
61- { temporaryReferences } ,
62- )
63- setPayload ( payload )
64- return payload . returnValue
65- } )
61+ { temporaryReferences }
62+ ) ;
63+ setPayload ( payload ) ;
64+ return payload . returnValue ;
65+ } ) ;
6666
6767 // hydration
6868 const browserRoot = (
6969 < React . StrictMode >
7070 < BrowserRoot />
7171 </ React . StrictMode >
72- )
72+ ) ;
7373 hydrateRoot ( document , browserRoot , {
7474 formState : initialPayload . formState ,
75- } )
75+ } ) ;
7676
7777 // implement server HMR by trigering re-fetch/render of RSC upon server code change
7878 if ( import . meta. hot ) {
79- import . meta. hot . on ( ' rsc:update' , ( ) => {
80- fetchRscPayload ( )
81- } )
79+ import . meta. hot . on ( " rsc:update" , ( ) => {
80+ fetchRscPayload ( ) ;
81+ } ) ;
8282 }
8383}
8484
8585// a little helper to setup events interception for client side navigation
8686function listenNavigation ( onNavigation : ( ) => void ) {
87- window . addEventListener ( ' popstate' , onNavigation )
88-
89- const oldPushState = window . history . pushState
90- window . history . pushState = function ( ...args ) {
91- const res = oldPushState . apply ( this , args )
92- onNavigation ( )
93- return res
94- }
95-
96- const oldReplaceState = window . history . replaceState
97- window . history . replaceState = function ( ...args ) {
98- const res = oldReplaceState . apply ( this , args )
99- onNavigation ( )
100- return res
101- }
87+ globalThis . addEventListener ( " popstate" , onNavigation ) ;
88+
89+ const oldPushState = globalThis . history . pushState ;
90+ globalThis . history . pushState = function ( ...args ) {
91+ const res = oldPushState . apply ( this , args ) ;
92+ onNavigation ( ) ;
93+ return res ;
94+ } ;
95+
96+ const oldReplaceState = globalThis . history . replaceState ;
97+ globalThis . history . replaceState = function ( ...args ) {
98+ const res = oldReplaceState . apply ( this , args ) ;
99+ onNavigation ( ) ;
100+ return res ;
101+ } ;
102102
103103 function onClick ( e : MouseEvent ) {
104- let link = ( e . target as Element ) . closest ( 'a' )
104+ const link = ( e . target as Element ) . closest ( "a" ) ;
105105 if (
106106 link &&
107107 link instanceof HTMLAnchorElement &&
108108 link . href &&
109- ( ! link . target || link . target === ' _self' ) &&
109+ ( ! link . target || link . target === " _self" ) &&
110110 link . origin === location . origin &&
111- ! link . hasAttribute ( ' download' ) &&
111+ ! link . hasAttribute ( " download" ) &&
112112 e . button === 0 && // left clicks only
113113 ! e . metaKey && // open in new tab (mac)
114114 ! e . ctrlKey && // open in new tab (windows)
115115 ! e . altKey && // download
116116 ! e . shiftKey &&
117117 ! e . defaultPrevented
118118 ) {
119- e . preventDefault ( )
120- history . pushState ( null , '' , link . href )
119+ e . preventDefault ( ) ;
120+ history . pushState ( null , "" , link . href ) ;
121121 }
122122 }
123- document . addEventListener ( ' click' , onClick )
123+ document . addEventListener ( " click" , onClick ) ;
124124
125125 return ( ) => {
126- document . removeEventListener ( ' click' , onClick )
127- window . removeEventListener ( ' popstate' , onNavigation )
128- window . history . pushState = oldPushState
129- window . history . replaceState = oldReplaceState
130- }
126+ document . removeEventListener ( " click" , onClick ) ;
127+ globalThis . removeEventListener ( " popstate" , onNavigation ) ;
128+ globalThis . history . pushState = oldPushState ;
129+ globalThis . history . replaceState = oldReplaceState ;
130+ } ;
131131}
132132
133- main ( )
133+ // eslint-disable-next-line unicorn/prefer-top-level-await
134+ main ( ) ;
0 commit comments