Skip to content

Commit 0c61265

Browse files
wardpeetLekoArts
andauthoredMar 15, 2022
fix: compatibility with react rc 2 (#35108)
Co-authored-by: Lennart <lekoarts@gmail.com>
1 parent 35c4a93 commit 0c61265

File tree

31 files changed

+195
-132
lines changed

31 files changed

+195
-132
lines changed
 

‎packages/gatsby-link/package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@
2121
},
2222
"peerDependencies": {
2323
"@gatsbyjs/reach-router": "^1.3.5",
24-
"react": "^16.9.0 || ^17.0.0",
25-
"react-dom": "^16.9.0 || ^17.0.0"
24+
"react": "^16.9.0 || ^17.0.0 || ^18.0.0",
25+
"react-dom": "^16.9.0 || ^17.0.0 || ^18.0.0"
2626
},
2727
"homepage": "https://github.com/gatsbyjs/gatsby/tree/master/packages/gatsby-link#readme",
2828
"keywords": [

‎packages/gatsby-plugin-cxs/package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@
2828
"peerDependencies": {
2929
"cxs": ">=5.0.0",
3030
"gatsby": "^4.0.0-next",
31-
"react": "^16.9.0 || ^17.0.0",
32-
"react-dom": "^16.9.0 || ^17.0.0"
31+
"react": "^16.9.0 || ^17.0.0 || ^18.0.0",
32+
"react-dom": "^16.9.0 || ^17.0.0 || ^18.0.0"
3333
},
3434
"repository": {
3535
"type": "git",

‎packages/gatsby-plugin-feed/package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@
3333
"main": "index.js",
3434
"peerDependencies": {
3535
"gatsby": "^4.0.0-next",
36-
"react": "^16.9.0 || ^17.0.0",
37-
"react-dom": "^16.9.0 || ^17.0.0"
36+
"react": "^16.9.0 || ^17.0.0 || ^18.0.0",
37+
"react-dom": "^16.9.0 || ^17.0.0 || ^18.0.0"
3838
},
3939
"repository": {
4040
"type": "git",

‎packages/gatsby-plugin-fullstory/package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@
3434
},
3535
"peerDependencies": {
3636
"gatsby": "^4.0.0-next",
37-
"react": "^16.9.0 || ^17.0.0",
38-
"react-dom": "^16.9.0 || ^17.0.0"
37+
"react": "^16.9.0 || ^17.0.0 || ^18.0.0",
38+
"react-dom": "^16.9.0 || ^17.0.0 || ^18.0.0"
3939
},
4040
"engines": {
4141
"node": ">=14.15.0"

‎packages/gatsby-plugin-google-analytics/package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@
2828
"main": "index.js",
2929
"peerDependencies": {
3030
"gatsby": "^4.0.0-next",
31-
"react": "^16.9.0 || ^17.0.0",
32-
"react-dom": "^16.9.0 || ^17.0.0"
31+
"react": "^16.9.0 || ^17.0.0 || ^18.0.0",
32+
"react-dom": "^16.9.0 || ^17.0.0 || ^18.0.0"
3333
},
3434
"repository": {
3535
"type": "git",

‎packages/gatsby-plugin-google-gtag/package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@
2727
"main": "index.js",
2828
"peerDependencies": {
2929
"gatsby": "^4.0.0-next",
30-
"react": "^16.9.0 || ^17.0.0",
31-
"react-dom": "^16.9.0 || ^17.0.0"
30+
"react": "^16.9.0 || ^17.0.0 || ^18.0.0",
31+
"react-dom": "^16.9.0 || ^17.0.0 || ^18.0.0"
3232
},
3333
"repository": {
3434
"type": "git",

‎packages/gatsby-plugin-google-tagmanager/package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@
2828
"main": "index.js",
2929
"peerDependencies": {
3030
"gatsby": "^4.0.0-next",
31-
"react": "^16.9.0 || ^17.0.0",
32-
"react-dom": "^16.9.0 || ^17.0.0"
31+
"react": "^16.9.0 || ^17.0.0 || ^18.0.0",
32+
"react-dom": "^16.9.0 || ^17.0.0 || ^18.0.0"
3333
},
3434
"repository": {
3535
"type": "git",

‎packages/gatsby-plugin-image/package.json

+5-4
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@
4949
"@types/fs-extra": "^9.0.13",
5050
"@types/node": "^14.10.2",
5151
"@types/prop-types": "^15.7.3",
52-
"@types/react": "^16.9.56",
53-
"@types/react-dom": "^16.9.8",
52+
"@types/react": "^17.0.40",
53+
"@types/react-dom": "^17.0.13",
5454
"ast-pretty-print": "^2.0.1",
5555
"babel-plugin-macros": "^2.8.0",
5656
"cross-env": "^7.0.3",
@@ -60,6 +60,7 @@
6060
"microbundle": "^0.13.0",
6161
"npm-run-all": "^4.1.5",
6262
"postcss": "^8.2.9",
63+
"semver": "^7.0.0",
6364
"terser": "^5.3.8",
6465
"typescript": "^4.5.5"
6566
},
@@ -68,8 +69,8 @@
6869
"gatsby": "^4.0.0-next",
6970
"gatsby-plugin-sharp": "^4.0.0-next",
7071
"gatsby-source-filesystem": "^4.0.0-next",
71-
"react": "^16.9.0 || ^17.0.0",
72-
"react-dom": "^16.9.0 || ^17.0.0"
72+
"react": "^16.9.0 || ^17.0.0 || ^18.0.0",
73+
"react-dom": "^16.9.0 || ^17.0.0 || ^18.0.0"
7374
},
7475
"dependencies": {
7576
"@babel/code-frame": "^7.14.0",

‎packages/gatsby-plugin-image/src/components/__tests__/gatsby-image.browser.tsx

+5-3
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
*/
44

55
import React from "react"
6-
import { GatsbyImage, IGatsbyImageData } from "../gatsby-image.browser"
76
import { render, waitFor } from "@testing-library/react"
87
import * as hooks from "../hooks"
8+
import type { IGatsbyImageData } from "../gatsby-image.browser"
99

1010
// Prevents terser for bailing because we're not in a babel plugin
1111
jest.mock(
@@ -20,15 +20,16 @@ jest.mock(
2020
describe(`GatsbyImage browser`, () => {
2121
let beforeHydrationContent: HTMLDivElement
2222
let image: IGatsbyImageData
23+
let GatsbyImage
2324

2425
beforeEach(() => {
2526
console.warn = jest.fn()
2627
console.error = jest.fn()
2728
global.SERVER = true
2829
global.GATSBY___IMAGE = true
29-
})
30+
global.HAS_REACT_18 = false
3031

31-
beforeEach(() => {
32+
GatsbyImage = require(`../gatsby-image.browser`).GatsbyImage
3233
image = {
3334
width: 100,
3435
height: 100,
@@ -80,6 +81,7 @@ describe(`GatsbyImage browser`, () => {
8081
jest.clearAllMocks()
8182
global.SERVER = undefined
8283
global.GATSBY___IMAGE = undefined
84+
global.HAS_REACT_18 = undefined
8385
process.env.NODE_ENV = `test`
8486
})
8587

‎packages/gatsby-plugin-image/src/components/__tests__/hooks.ts

+2-8
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,6 @@
11
import { Node } from "gatsby"
2-
import {
3-
getSrc,
4-
getSrcSet,
5-
getImage,
6-
IGatsbyImageData,
7-
IGetImageDataArgs,
8-
} from "../../"
9-
import { getImageData } from "../hooks"
2+
import { getImageData, getSrc, getSrcSet, getImage } from "../hooks"
3+
import type { IGatsbyImageData, IGetImageDataArgs } from "../../"
104

115
const imageData: IGatsbyImageData = {
126
images: {

‎packages/gatsby-plugin-image/src/components/gatsby-image.browser.tsx

+36-3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/* global HAS_REACT_18 */
12
/* eslint-disable no-unused-expressions */
23
import React, {
34
Component,
@@ -22,7 +23,33 @@ import { Layout } from "../image-utils"
2223
import { getSizer } from "./layout-wrapper"
2324
import { propTypes } from "./gatsby-image.server"
2425
import { Unobserver } from "./intersection-observer"
25-
import { render } from "react-dom"
26+
import type { Root } from "react-dom/client"
27+
28+
let reactRender
29+
if (HAS_REACT_18) {
30+
const reactDomClient = require(`react-dom/client`)
31+
reactRender = (
32+
Component: React.ReactChild | Iterable<React.ReactNode>,
33+
el: ReactDOM.Container,
34+
root: Root
35+
): Root => {
36+
if (!root) {
37+
root = reactDomClient.createRoot(el)
38+
}
39+
40+
root.render(Component)
41+
42+
return root
43+
}
44+
} else {
45+
const reactDomClient = require(`react-dom`)
46+
reactRender = (
47+
Component: React.ReactChild | Iterable<React.ReactNode>,
48+
el: ReactDOM.Container
49+
): void => {
50+
reactDomClient.render(Component, el)
51+
}
52+
}
2653

2754
// eslint-disable-next-line @typescript-eslint/naming-convention
2855
export interface GatsbyImageProps
@@ -69,6 +96,7 @@ class GatsbyImageHydrator extends Component<
6996
lazyHydrator: () => void | null = null
7097
ref = createRef<HTMLImageElement>()
7198
unobserveRef: Unobserver
99+
reactRootRef: MutableRefObject<Root> = createRef()
72100

73101
constructor(props) {
74102
super(props)
@@ -108,7 +136,8 @@ class GatsbyImageHydrator extends Component<
108136
},
109137
this.root,
110138
this.hydrated,
111-
this.forceRender
139+
this.forceRender,
140+
this.reactRootRef
112141
)
113142
})
114143
}
@@ -152,7 +181,11 @@ class GatsbyImageHydrator extends Component<
152181

153182
// // on unmount, make sure we cleanup
154183
if (this.hydrated.current && this.lazyHydrator) {
155-
render(null, this.root.current)
184+
this.reactRootRef.current = reactRender(
185+
null,
186+
this.root.current,
187+
this.reactRootRef.current
188+
)
156189
}
157190
}
158191

‎packages/gatsby-plugin-image/src/components/lazy-hydrate.tsx

+49-24
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1+
/* global HAS_REACT_18 */
12
import React, { MutableRefObject } from "react"
2-
import ReactDOM from "react-dom"
33
import { GatsbyImageProps } from "./gatsby-image.browser"
44
import { LayoutWrapper } from "./layout-wrapper"
55
import { Placeholder } from "./placeholder"
66
import { MainImageProps, MainImage } from "./main-image"
77
import { getMainProps, getPlaceholderProps } from "./hooks"
88
import { ReactElement } from "react"
9+
import type { Root } from "react-dom/client"
910

1011
type LazyHydrateProps = Omit<GatsbyImageProps, "as" | "style" | "className"> & {
1112
isLoading: boolean
@@ -14,6 +15,38 @@ type LazyHydrateProps = Omit<GatsbyImageProps, "as" | "style" | "className"> & {
1415
ref: MutableRefObject<HTMLImageElement | undefined>
1516
}
1617

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+
1750
export function lazyHydrate(
1851
{
1952
image,
@@ -31,7 +64,8 @@ export function lazyHydrate(
3164
}: LazyHydrateProps,
3265
root: MutableRefObject<HTMLElement | undefined>,
3366
hydrated: MutableRefObject<boolean>,
34-
forceHydrate: MutableRefObject<boolean>
67+
forceHydrate: MutableRefObject<boolean>,
68+
reactRootRef: MutableRefObject<Root>
3569
): (() => void) | null {
3670
const {
3771
width,
@@ -87,34 +121,25 @@ export function lazyHydrate(
87121

88122
if (root.current) {
89123
// 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+
)
99130
} 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)
106132
}
133+
hydrated.current = true
107134
}
108135

109136
return (): void => {
110137
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+
)
118143
}
119144
}
120145
}

‎packages/gatsby-plugin-image/src/gatsby-node.ts

+4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
ImageLayoutType,
66
ImagePlaceholderType,
77
} from "./resolver-utils"
8+
import { major } from "semver"
89

910
export * from "./node-apis/preprocess-source"
1011

@@ -51,6 +52,9 @@ export const onCreateWebpackConfig: GatsbyNode["onCreateWebpackConfig"] = ({
5152
plugins.define({
5253
// eslint-disable-next-line @typescript-eslint/naming-convention
5354
GATSBY___IMAGE: true,
55+
HAS_REACT_18: JSON.stringify(
56+
major(require(`react-dom/package.json`).version) >= 18
57+
),
5458
}),
5559
],
5660
})

‎packages/gatsby-plugin-image/src/global.d.ts

+1
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@ export {}
33
declare global {
44
declare var SERVER: boolean | undefined
55
declare var GATSBY___IMAGE: boolean | undefined
6+
declare var HAS_REACT_18: boolean | undefined
67
}

‎packages/gatsby-plugin-jss/package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@
2626
"main": "index.js",
2727
"peerDependencies": {
2828
"gatsby": "^4.0.0-next",
29-
"react": "^16.9.0 || ^17.0.0",
30-
"react-dom": "^16.9.0 || ^17.0.0"
29+
"react": "^16.9.0 || ^17.0.0 || ^18.0.0",
30+
"react-dom": "^16.9.0 || ^17.0.0 || ^18.0.0"
3131
},
3232
"repository": {
3333
"type": "git",

‎packages/gatsby-plugin-mdx/package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717
"@mdx-js/mdx": "^1.0.0",
1818
"@mdx-js/react": "^1.0.0",
1919
"gatsby": "^4.0.0-next",
20-
"react": "^16.9.0 || ^17.0.0",
21-
"react-dom": "^16.9.0 || ^17.0.0"
20+
"react": "^16.9.0 || ^17.0.0 || ^18.0.0",
21+
"react-dom": "^16.9.0 || ^17.0.0 || ^18.0.0"
2222
},
2323
"dependencies": {
2424
"@babel/core": "^7.15.5",

‎packages/gatsby-plugin-netlify-cms/package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@
3838
"peerDependencies": {
3939
"gatsby": "^4.0.0-next",
4040
"netlify-cms-app": "^2.9.0",
41-
"react": "^16.9.0 || ^17.0.0",
42-
"react-dom": "^16.9.0 || ^17.0.0",
41+
"react": "^16.9.0 || ^17.0.0 || ^18.0.0",
42+
"react-dom": "^16.9.0 || ^17.0.0 || ^18.0.0",
4343
"webpack": "^5.0.0"
4444
},
4545
"repository": {

0 commit comments

Comments
 (0)
Please sign in to comment.