@@ -168,11 +168,7 @@ function useModernSSRSafeId(defaultId?: string): string {
168
168
export const useSSRSafeId : typeof useModernSSRSafeId | typeof useLegacySSRSafeId = typeof React [ 'useId' ] === 'function' ? useModernSSRSafeId : useLegacySSRSafeId ;
169
169
170
170
function getSnapshot ( ) {
171
- return false ;
172
- }
173
-
174
- function getServerSnapshot ( ) {
175
- return true ;
171
+ return null ;
176
172
}
177
173
178
174
// eslint-disable-next-line @typescript-eslint/no-unused-vars
@@ -181,17 +177,38 @@ function subscribe(onStoreChange: () => void): () => void {
181
177
return ( ) => { } ;
182
178
}
183
179
180
+ function useModernIsSSR ( ) : boolean {
181
+ let initialState = false ;
182
+ // In React 18, we can use useSyncExternalStore to detect if we're server rendering or hydrating.
183
+ React . useSyncExternalStore ( subscribe , getSnapshot , ( ) => {
184
+ initialState = true ;
185
+
186
+ // Important! We must return the same value for both server and client to avoid unnecessary render
187
+ return getSnapshot ( ) ;
188
+ } ) ;
189
+ let [ isSSR , setIsSSR ] = useState ( initialState ) ;
190
+
191
+ useLayoutEffect ( ( ) => {
192
+ if ( ! isSSR ) {
193
+ return ;
194
+ }
195
+
196
+ React . startTransition ( ( ) => {
197
+ setIsSSR ( false ) ;
198
+ } ) ;
199
+ } , [ isSSR ] ) ;
200
+
201
+ return isSSR ;
202
+ }
203
+
204
+ function useLegacyIsSSR ( ) : boolean {
205
+ return useContext ( IsSSRContext ) ;
206
+ }
207
+
208
+ // Use React.useSyncExternalStore and React.startTransition in React >=18 if available, otherwise fall back to our old implementation.
184
209
/**
185
210
* Returns whether the component is currently being server side rendered or
186
211
* hydrated on the client. Can be used to delay browser-specific rendering
187
212
* until after hydration.
188
213
*/
189
- export function useIsSSR ( ) : boolean {
190
- // In React 18, we can use useSyncExternalStore to detect if we're server rendering or hydrating.
191
- if ( typeof React [ 'useSyncExternalStore' ] === 'function' ) {
192
- return React [ 'useSyncExternalStore' ] ( subscribe , getSnapshot , getServerSnapshot ) ;
193
- }
194
-
195
- // eslint-disable-next-line react-hooks/rules-of-hooks
196
- return useContext ( IsSSRContext ) ;
197
- }
214
+ export const useIsSSR : ( ) => boolean = typeof React [ 'startTransition' ] === 'function' ? useModernIsSSR : useLegacyIsSSR ;
0 commit comments