@@ -25,7 +25,13 @@ const xr8ApiKey: string | undefined = import.meta.env.VITE_XR8_API_KEY;
2525const touchSupported =
2626 typeof document !== "undefined" && "ontouchend" in document ;
2727
28- export const App = ( { loading = false } : { loading ?: boolean } ) => {
28+ const useIsSSR = ( ) => {
29+ const [ isSSR , setNotSSR ] = React . useReducer ( ( _ : boolean ) => false , true ) ;
30+ React . useEffect ( setNotSSR , [ ] ) ;
31+ return isSSR ;
32+ } ;
33+
34+ export const App = ( ) => {
2935 let [ state , setState ] = React . useState <
3036 | { type : "loading" }
3137 | { type : "waiting-user-input" }
@@ -44,8 +50,8 @@ export const App = ({ loading = false }: { loading?: boolean }) => {
4450 | { type : "flat" }
4551 > ( { type : "waiting-user-input" } ) ;
4652
47- // force the state to loading
48- if ( loading ) state = { type : "loading" } ;
53+ // force the state to be loading in SSR
54+ if ( useIsSSR ( ) ) state = { type : "loading" } ;
4955
5056 const uiTunnel = React . useMemo ( tunnel , [ ] ) ;
5157
@@ -100,66 +106,68 @@ export const App = ({ loading = false }: { loading?: boolean }) => {
100106
101107 return (
102108 < >
103- < CanvasContainerPortal >
104- < Canvas
105- camera = { {
106- position : new THREE . Vector3 ( 0 , 6 , 6 ) ,
107- near : 0.1 ,
108- far : 1000 ,
109- } }
110- shadows
111- style = { {
112- position : "fixed" ,
113- top : 0 ,
114- left : 0 ,
115- right : 0 ,
116- bottom : 0 ,
117- touchAction : "none" ,
118- opacity : readyForRender ? 1 : 0 ,
119- } }
120- >
121- { state . type === "xr8" && state . xr8 && (
122- < XR8Controls
123- xr8 = { state . xr8 }
124- onPoseFound = { ( ) => setState ( ( s ) => ( { ...s , poseFound : true } ) ) }
125- onCameraFeedDisplayed = { ( ) =>
126- setState ( ( s ) => ( { ...s , cameraFeedDisplayed : true } ) )
109+ { state . type !== "loading" && (
110+ < CanvasContainerPortal >
111+ < Canvas
112+ camera = { {
113+ position : new THREE . Vector3 ( 0 , 6 , 6 ) ,
114+ near : 0.1 ,
115+ far : 1000 ,
116+ } }
117+ shadows
118+ style = { {
119+ position : "fixed" ,
120+ top : 0 ,
121+ left : 0 ,
122+ right : 0 ,
123+ bottom : 0 ,
124+ touchAction : "none" ,
125+ opacity : readyForRender ? 1 : 0 ,
126+ } }
127+ >
128+ { state . type === "xr8" && state . xr8 && (
129+ < XR8Controls
130+ xr8 = { state . xr8 }
131+ onPoseFound = { ( ) => setState ( ( s ) => ( { ...s , poseFound : true } ) ) }
132+ onCameraFeedDisplayed = { ( ) =>
133+ setState ( ( s ) => ( { ...s , cameraFeedDisplayed : true } ) )
134+ }
135+ />
136+ ) }
137+
138+ { state . type === "webXR" && state . webXRSession && (
139+ < WebXRControls
140+ worldSize = { 8 }
141+ webXRSession = { state . webXRSession }
142+ onPoseFound = { ( ) => setState ( ( s ) => ( { ...s , poseFound : true } ) ) }
143+ onCameraFeedDisplayed = { ( ) =>
144+ setState ( ( s ) => ( { ...s , cameraFeedDisplayed : true } ) )
145+ }
146+ />
147+ ) }
148+
149+ < React . Suspense fallback = { null } >
150+ < Environment />
151+
152+ {
153+ /* preload the dice model */
154+ ! readyForGame && (
155+ < Dice
156+ position = { [ 999 , 999 , 9999 ] }
157+ scale = { [ 0.0001 , 0.0001 , 0.0001 ] }
158+ />
159+ )
127160 }
128- />
129- ) }
130-
131- { state . type === "webXR" && state . webXRSession && (
132- < WebXRControls
133- worldSize = { 8 }
134- webXRSession = { state . webXRSession }
135- onPoseFound = { ( ) => setState ( ( s ) => ( { ...s , poseFound : true } ) ) }
136- onCameraFeedDisplayed = { ( ) =>
137- setState ( ( s ) => ( { ...s , cameraFeedDisplayed : true } ) )
138- }
139- />
140- ) }
141-
142- < React . Suspense fallback = { null } >
143- < Environment />
144-
145- {
146- /* preload the dice model */
147- ! readyForGame && (
148- < Dice
149- position = { [ 999 , 999 , 9999 ] }
150- scale = { [ 0.0001 , 0.0001 , 0.0001 ] }
151- />
152- )
153- }
154161
155- { readyForGame && < Game UiPortal = { uiTunnel . In } /> }
156- </ React . Suspense >
162+ { readyForGame && < Game UiPortal = { uiTunnel . In } /> }
163+ </ React . Suspense >
157164
158- < directionalLight position = { [ 10 , 8 , 6 ] } intensity = { 0 } castShadow />
165+ < directionalLight position = { [ 10 , 8 , 6 ] } intensity = { 0 } castShadow />
159166
160- < Ground />
161- </ Canvas >
162- </ CanvasContainerPortal >
167+ < Ground />
168+ </ Canvas >
169+ </ CanvasContainerPortal >
170+ ) }
163171
164172 { false && < Visualizer /> }
165173
@@ -197,10 +205,8 @@ export const App = ({ loading = false }: { loading?: boolean }) => {
197205 ) ;
198206} ;
199207
200- const CanvasContainerPortal = ( { children } : { children ?: any } ) => {
201- if ( typeof document === "undefined" ) return null ;
202- return createPortal ( children , document . getElementById ( "canvas-container" ) ! ) ;
203- } ;
208+ const CanvasContainerPortal = ( { children } : { children ?: any } ) =>
209+ createPortal ( children , document . getElementById ( "canvas-container" ) ! ) ;
204210
205211const Over = ( { children } : { children ?: any } ) => (
206212 < div
0 commit comments