1
+ /* global HAS_REACT_18 */
1
2
import React , { MutableRefObject } from "react"
2
- import ReactDOM from "react-dom"
3
3
import { GatsbyImageProps } from "./gatsby-image.browser"
4
4
import { LayoutWrapper } from "./layout-wrapper"
5
5
import { Placeholder } from "./placeholder"
6
6
import { MainImageProps , MainImage } from "./main-image"
7
7
import { getMainProps , getPlaceholderProps } from "./hooks"
8
8
import { ReactElement } from "react"
9
+ import type { Root } from "react-dom/client"
9
10
10
11
type LazyHydrateProps = Omit < GatsbyImageProps , "as" | "style" | "className" > & {
11
12
isLoading : boolean
@@ -14,6 +15,38 @@ type LazyHydrateProps = Omit<GatsbyImageProps, "as" | "style" | "className"> & {
14
15
ref : MutableRefObject < HTMLImageElement | undefined >
15
16
}
16
17
18
+ let reactRender
19
+ let reactHydrate
20
+ if ( HAS_REACT_18 ) {
21
+ const reactDomClient = require ( `react-dom/client` )
22
+ reactRender = (
23
+ Component : React . ReactChild | Iterable < React . ReactNode > ,
24
+ el : ReactDOM . Container ,
25
+ root : Root
26
+ ) : Root => {
27
+ if ( ! root ) {
28
+ root = reactDomClient . createRoot ( el )
29
+ }
30
+
31
+ root . render ( Component )
32
+
33
+ return root
34
+ }
35
+ reactHydrate = (
36
+ Component : React . ReactChild | Iterable < React . ReactNode > ,
37
+ el : ReactDOM . Container
38
+ ) : Root => reactDomClient . hydrateRoot ( el , Component )
39
+ } else {
40
+ const reactDomClient = require ( `react-dom` )
41
+ reactRender = (
42
+ Component : React . ReactChild | Iterable < React . ReactNode > ,
43
+ el : ReactDOM . Container
44
+ ) : void => {
45
+ reactDomClient . render ( Component , el )
46
+ }
47
+ reactHydrate = reactDomClient . hydrate
48
+ }
49
+
17
50
export function lazyHydrate (
18
51
{
19
52
image,
@@ -31,7 +64,8 @@ export function lazyHydrate(
31
64
} : LazyHydrateProps ,
32
65
root : MutableRefObject < HTMLElement | undefined > ,
33
66
hydrated : MutableRefObject < boolean > ,
34
- forceHydrate : MutableRefObject < boolean >
67
+ forceHydrate : MutableRefObject < boolean > ,
68
+ reactRootRef : MutableRefObject < Root >
35
69
) : ( ( ) => void ) | null {
36
70
const {
37
71
width,
@@ -87,34 +121,25 @@ export function lazyHydrate(
87
121
88
122
if ( root . current ) {
89
123
// Force render to mitigate "Expected server HTML to contain a matching" in develop
90
- // @ts -ignore react 18 typings
91
- if ( ReactDOM . createRoot ) {
92
- if ( ! hydrated . current ) {
93
- // @ts -ignore react 18 typings
94
- hydrated . current = ReactDOM . createRoot ( root . current )
95
- }
96
-
97
- // @ts -ignore react 18 typings
98
- hydrated . current . render ( component )
124
+ if ( hydrated . current || forceHydrate . current || HAS_REACT_18 ) {
125
+ reactRootRef . current = reactRender (
126
+ component ,
127
+ root . current ,
128
+ reactRootRef . current
129
+ )
99
130
} else {
100
- const doRender =
101
- hydrated . current || forceHydrate . current
102
- ? ReactDOM . render
103
- : ReactDOM . hydrate
104
- doRender ( component , root . current )
105
- hydrated . current = true
131
+ reactHydrate ( component , root . current )
106
132
}
133
+ hydrated . current = true
107
134
}
108
135
109
136
return ( ) : void => {
110
137
if ( root . current ) {
111
- // @ts -ignore react 18 typings
112
- if ( ReactDOM . createRoot ) {
113
- // @ts -ignore react 18 typings
114
- hydrated . current . render ( null )
115
- } else {
116
- ReactDOM . render ( null as unknown as ReactElement , root . current )
117
- }
138
+ reactRender (
139
+ null as unknown as ReactElement ,
140
+ root . current ,
141
+ reactRootRef . current
142
+ )
118
143
}
119
144
}
120
145
}
0 commit comments