@@ -31,6 +31,15 @@ module.hot.accept([
31
31
32
32
window . ___emitter = emitter
33
33
34
+ if (
35
+ process . env . GATSBY_EXPERIMENTAL_CONCURRENT_FEATURES &&
36
+ ! ReactDOM . unstable_createRoot
37
+ ) {
38
+ throw new Error (
39
+ `The GATSBY_EXPERIMENTAL_CONCURRENT_FEATURES flag is not compatible with your React version. Please install "[email protected] " and "[email protected] " or higher.`
40
+ )
41
+ }
42
+
34
43
const loader = new DevLoader ( asyncRequires , matchPaths )
35
44
setLoader ( loader )
36
45
loader . setApiRunner ( apiRunner )
@@ -127,12 +136,25 @@ apiRunnerAsync(`onClientEntry`).then(() => {
127
136
const rootElement = document . getElementById ( `___gatsby` )
128
137
129
138
const focusEl = document . getElementById ( `gatsby-focus-wrapper` )
139
+
140
+ // Client only pages have any empty body so we just do a normal
141
+ // render to avoid React complaining about hydration mis-matches.
142
+ let defaultRenderer = ReactDOM . render
143
+ if ( focusEl && focusEl . children . length ) {
144
+ if (
145
+ process . env . GATSBY_EXPERIMENTAL_CONCURRENT_FEATURES &&
146
+ ReactDOM . unstable_createRoot
147
+ ) {
148
+ defaultRenderer = ReactDOM . unstable_createRoot
149
+ } else {
150
+ defaultRenderer = ReactDOM . hydrate
151
+ }
152
+ }
153
+
130
154
const renderer = apiRunner (
131
155
`replaceHydrateFunction` ,
132
156
undefined ,
133
- // Client only pages have any empty body so we just do a normal
134
- // render to avoid React complaining about hydration mis-matches.
135
- focusEl && focusEl . children . length > 0 ? ReactDOM . hydrate : ReactDOM . render
157
+ defaultRenderer
136
158
) [ 0 ]
137
159
138
160
let dismissLoadingIndicator
@@ -166,31 +188,57 @@ apiRunnerAsync(`onClientEntry`).then(() => {
166
188
] ) . then ( ( ) => {
167
189
navigationInit ( )
168
190
191
+ function onHydrated ( ) {
192
+ apiRunner ( `onInitialClientRender` )
193
+
194
+ // Render query on demand overlay
195
+ if (
196
+ process . env . GATSBY_QUERY_ON_DEMAND_LOADING_INDICATOR &&
197
+ process . env . GATSBY_QUERY_ON_DEMAND_LOADING_INDICATOR === `true`
198
+ ) {
199
+ const indicatorMountElement = document . createElement ( `div` )
200
+ indicatorMountElement . setAttribute (
201
+ `id` ,
202
+ `query-on-demand-indicator-element`
203
+ )
204
+ document . body . append ( indicatorMountElement )
205
+
206
+ if ( renderer === ReactDOM . unstable_createRoot ) {
207
+ renderer ( indicatorMountElement ) . render (
208
+ < LoadingIndicatorEventHandler />
209
+ )
210
+ } else {
211
+ renderer ( < LoadingIndicatorEventHandler /> , indicatorMountElement )
212
+ }
213
+ }
214
+ }
215
+
216
+ function App ( ) {
217
+ const onClientEntryRanRef = React . useRef ( false )
218
+
219
+ React . useEffect ( ( ) => {
220
+ if ( ! onClientEntryRanRef . current ) {
221
+ onClientEntryRanRef . current = true
222
+
223
+ onHydrated ( )
224
+ }
225
+ } , [ ] )
226
+
227
+ return < Root />
228
+ }
229
+
169
230
domReady ( ( ) => {
170
231
if ( dismissLoadingIndicator ) {
171
232
dismissLoadingIndicator ( )
172
233
}
173
234
174
- renderer ( < Root /> , rootElement , ( ) => {
175
- apiRunner ( `onInitialClientRender` )
176
-
177
- // Render query on demand overlay
178
- if (
179
- process . env . GATSBY_QUERY_ON_DEMAND_LOADING_INDICATOR &&
180
- process . env . GATSBY_QUERY_ON_DEMAND_LOADING_INDICATOR === `true`
181
- ) {
182
- const indicatorMountElement = document . createElement ( `div` )
183
- indicatorMountElement . setAttribute (
184
- `id` ,
185
- `query-on-demand-indicator-element`
186
- )
187
- document . body . append ( indicatorMountElement )
188
- ReactDOM . render (
189
- < LoadingIndicatorEventHandler /> ,
190
- indicatorMountElement
191
- )
192
- }
193
- } )
235
+ if ( renderer === ReactDOM . unstable_createRoot ) {
236
+ renderer ( rootElement , {
237
+ hydrate : true ,
238
+ } ) . render ( < App /> )
239
+ } else {
240
+ renderer ( < App /> , rootElement )
241
+ }
194
242
} )
195
243
} )
196
244
} )
0 commit comments