Skip to content

Commit

Permalink
fix: compatibility with react rc 2 (#35108)
Browse files Browse the repository at this point in the history
Co-authored-by: Lennart <lekoarts@gmail.com>
  • Loading branch information
wardpeet and LekoArts committed Mar 15, 2022
1 parent 35c4a93 commit 0c61265
Show file tree
Hide file tree
Showing 31 changed files with 195 additions and 132 deletions.
4 changes: 2 additions & 2 deletions packages/gatsby-link/package.json
Expand Up @@ -21,8 +21,8 @@
},
"peerDependencies": {
"@gatsbyjs/reach-router": "^1.3.5",
"react": "^16.9.0 || ^17.0.0",
"react-dom": "^16.9.0 || ^17.0.0"
"react": "^16.9.0 || ^17.0.0 || ^18.0.0",
"react-dom": "^16.9.0 || ^17.0.0 || ^18.0.0"
},
"homepage": "https://github.com/gatsbyjs/gatsby/tree/master/packages/gatsby-link#readme",
"keywords": [
Expand Down
4 changes: 2 additions & 2 deletions packages/gatsby-plugin-cxs/package.json
Expand Up @@ -28,8 +28,8 @@
"peerDependencies": {
"cxs": ">=5.0.0",
"gatsby": "^4.0.0-next",
"react": "^16.9.0 || ^17.0.0",
"react-dom": "^16.9.0 || ^17.0.0"
"react": "^16.9.0 || ^17.0.0 || ^18.0.0",
"react-dom": "^16.9.0 || ^17.0.0 || ^18.0.0"
},
"repository": {
"type": "git",
Expand Down
4 changes: 2 additions & 2 deletions packages/gatsby-plugin-feed/package.json
Expand Up @@ -33,8 +33,8 @@
"main": "index.js",
"peerDependencies": {
"gatsby": "^4.0.0-next",
"react": "^16.9.0 || ^17.0.0",
"react-dom": "^16.9.0 || ^17.0.0"
"react": "^16.9.0 || ^17.0.0 || ^18.0.0",
"react-dom": "^16.9.0 || ^17.0.0 || ^18.0.0"
},
"repository": {
"type": "git",
Expand Down
4 changes: 2 additions & 2 deletions packages/gatsby-plugin-fullstory/package.json
Expand Up @@ -34,8 +34,8 @@
},
"peerDependencies": {
"gatsby": "^4.0.0-next",
"react": "^16.9.0 || ^17.0.0",
"react-dom": "^16.9.0 || ^17.0.0"
"react": "^16.9.0 || ^17.0.0 || ^18.0.0",
"react-dom": "^16.9.0 || ^17.0.0 || ^18.0.0"
},
"engines": {
"node": ">=14.15.0"
Expand Down
4 changes: 2 additions & 2 deletions packages/gatsby-plugin-google-analytics/package.json
Expand Up @@ -28,8 +28,8 @@
"main": "index.js",
"peerDependencies": {
"gatsby": "^4.0.0-next",
"react": "^16.9.0 || ^17.0.0",
"react-dom": "^16.9.0 || ^17.0.0"
"react": "^16.9.0 || ^17.0.0 || ^18.0.0",
"react-dom": "^16.9.0 || ^17.0.0 || ^18.0.0"
},
"repository": {
"type": "git",
Expand Down
4 changes: 2 additions & 2 deletions packages/gatsby-plugin-google-gtag/package.json
Expand Up @@ -27,8 +27,8 @@
"main": "index.js",
"peerDependencies": {
"gatsby": "^4.0.0-next",
"react": "^16.9.0 || ^17.0.0",
"react-dom": "^16.9.0 || ^17.0.0"
"react": "^16.9.0 || ^17.0.0 || ^18.0.0",
"react-dom": "^16.9.0 || ^17.0.0 || ^18.0.0"
},
"repository": {
"type": "git",
Expand Down
4 changes: 2 additions & 2 deletions packages/gatsby-plugin-google-tagmanager/package.json
Expand Up @@ -28,8 +28,8 @@
"main": "index.js",
"peerDependencies": {
"gatsby": "^4.0.0-next",
"react": "^16.9.0 || ^17.0.0",
"react-dom": "^16.9.0 || ^17.0.0"
"react": "^16.9.0 || ^17.0.0 || ^18.0.0",
"react-dom": "^16.9.0 || ^17.0.0 || ^18.0.0"
},
"repository": {
"type": "git",
Expand Down
9 changes: 5 additions & 4 deletions packages/gatsby-plugin-image/package.json
Expand Up @@ -49,8 +49,8 @@
"@types/fs-extra": "^9.0.13",
"@types/node": "^14.10.2",
"@types/prop-types": "^15.7.3",
"@types/react": "^16.9.56",
"@types/react-dom": "^16.9.8",
"@types/react": "^17.0.40",
"@types/react-dom": "^17.0.13",
"ast-pretty-print": "^2.0.1",
"babel-plugin-macros": "^2.8.0",
"cross-env": "^7.0.3",
Expand All @@ -60,6 +60,7 @@
"microbundle": "^0.13.0",
"npm-run-all": "^4.1.5",
"postcss": "^8.2.9",
"semver": "^7.0.0",
"terser": "^5.3.8",
"typescript": "^4.5.5"
},
Expand All @@ -68,8 +69,8 @@
"gatsby": "^4.0.0-next",
"gatsby-plugin-sharp": "^4.0.0-next",
"gatsby-source-filesystem": "^4.0.0-next",
"react": "^16.9.0 || ^17.0.0",
"react-dom": "^16.9.0 || ^17.0.0"
"react": "^16.9.0 || ^17.0.0 || ^18.0.0",
"react-dom": "^16.9.0 || ^17.0.0 || ^18.0.0"
},
"dependencies": {
"@babel/code-frame": "^7.14.0",
Expand Down
Expand Up @@ -3,9 +3,9 @@
*/

import React from "react"
import { GatsbyImage, IGatsbyImageData } from "../gatsby-image.browser"
import { render, waitFor } from "@testing-library/react"
import * as hooks from "../hooks"
import type { IGatsbyImageData } from "../gatsby-image.browser"

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

beforeEach(() => {
console.warn = jest.fn()
console.error = jest.fn()
global.SERVER = true
global.GATSBY___IMAGE = true
})
global.HAS_REACT_18 = false

beforeEach(() => {
GatsbyImage = require(`../gatsby-image.browser`).GatsbyImage
image = {
width: 100,
height: 100,
Expand Down Expand Up @@ -80,6 +81,7 @@ describe(`GatsbyImage browser`, () => {
jest.clearAllMocks()
global.SERVER = undefined
global.GATSBY___IMAGE = undefined
global.HAS_REACT_18 = undefined
process.env.NODE_ENV = `test`
})

Expand Down
10 changes: 2 additions & 8 deletions packages/gatsby-plugin-image/src/components/__tests__/hooks.ts
@@ -1,12 +1,6 @@
import { Node } from "gatsby"
import {
getSrc,
getSrcSet,
getImage,
IGatsbyImageData,
IGetImageDataArgs,
} from "../../"
import { getImageData } from "../hooks"
import { getImageData, getSrc, getSrcSet, getImage } from "../hooks"
import type { IGatsbyImageData, IGetImageDataArgs } from "../../"

const imageData: IGatsbyImageData = {
images: {
Expand Down
@@ -1,3 +1,4 @@
/* global HAS_REACT_18 */
/* eslint-disable no-unused-expressions */
import React, {
Component,
Expand All @@ -22,7 +23,33 @@ import { Layout } from "../image-utils"
import { getSizer } from "./layout-wrapper"
import { propTypes } from "./gatsby-image.server"
import { Unobserver } from "./intersection-observer"
import { render } from "react-dom"
import type { Root } from "react-dom/client"

let reactRender
if (HAS_REACT_18) {
const reactDomClient = require(`react-dom/client`)
reactRender = (
Component: React.ReactChild | Iterable<React.ReactNode>,
el: ReactDOM.Container,
root: Root
): Root => {
if (!root) {
root = reactDomClient.createRoot(el)
}

root.render(Component)

return root
}
} else {
const reactDomClient = require(`react-dom`)
reactRender = (
Component: React.ReactChild | Iterable<React.ReactNode>,
el: ReactDOM.Container
): void => {
reactDomClient.render(Component, el)
}
}

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

constructor(props) {
super(props)
Expand Down Expand Up @@ -108,7 +136,8 @@ class GatsbyImageHydrator extends Component<
},
this.root,
this.hydrated,
this.forceRender
this.forceRender,
this.reactRootRef
)
})
}
Expand Down Expand Up @@ -152,7 +181,11 @@ class GatsbyImageHydrator extends Component<

// // on unmount, make sure we cleanup
if (this.hydrated.current && this.lazyHydrator) {
render(null, this.root.current)
this.reactRootRef.current = reactRender(
null,
this.root.current,
this.reactRootRef.current
)
}
}

Expand Down
73 changes: 49 additions & 24 deletions packages/gatsby-plugin-image/src/components/lazy-hydrate.tsx
@@ -1,11 +1,12 @@
/* global HAS_REACT_18 */
import React, { MutableRefObject } from "react"
import ReactDOM from "react-dom"
import { GatsbyImageProps } from "./gatsby-image.browser"
import { LayoutWrapper } from "./layout-wrapper"
import { Placeholder } from "./placeholder"
import { MainImageProps, MainImage } from "./main-image"
import { getMainProps, getPlaceholderProps } from "./hooks"
import { ReactElement } from "react"
import type { Root } from "react-dom/client"

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

let reactRender
let reactHydrate
if (HAS_REACT_18) {
const reactDomClient = require(`react-dom/client`)
reactRender = (
Component: React.ReactChild | Iterable<React.ReactNode>,
el: ReactDOM.Container,
root: Root
): Root => {
if (!root) {
root = reactDomClient.createRoot(el)
}

root.render(Component)

return root
}
reactHydrate = (
Component: React.ReactChild | Iterable<React.ReactNode>,
el: ReactDOM.Container
): Root => reactDomClient.hydrateRoot(el, Component)
} else {
const reactDomClient = require(`react-dom`)
reactRender = (
Component: React.ReactChild | Iterable<React.ReactNode>,
el: ReactDOM.Container
): void => {
reactDomClient.render(Component, el)
}
reactHydrate = reactDomClient.hydrate
}

export function lazyHydrate(
{
image,
Expand All @@ -31,7 +64,8 @@ export function lazyHydrate(
}: LazyHydrateProps,
root: MutableRefObject<HTMLElement | undefined>,
hydrated: MutableRefObject<boolean>,
forceHydrate: MutableRefObject<boolean>
forceHydrate: MutableRefObject<boolean>,
reactRootRef: MutableRefObject<Root>
): (() => void) | null {
const {
width,
Expand Down Expand Up @@ -87,34 +121,25 @@ export function lazyHydrate(

if (root.current) {
// Force render to mitigate "Expected server HTML to contain a matching" in develop
// @ts-ignore react 18 typings
if (ReactDOM.createRoot) {
if (!hydrated.current) {
// @ts-ignore react 18 typings
hydrated.current = ReactDOM.createRoot(root.current)
}

// @ts-ignore react 18 typings
hydrated.current.render(component)
if (hydrated.current || forceHydrate.current || HAS_REACT_18) {
reactRootRef.current = reactRender(
component,
root.current,
reactRootRef.current
)
} else {
const doRender =
hydrated.current || forceHydrate.current
? ReactDOM.render
: ReactDOM.hydrate
doRender(component, root.current)
hydrated.current = true
reactHydrate(component, root.current)
}
hydrated.current = true
}

return (): void => {
if (root.current) {
// @ts-ignore react 18 typings
if (ReactDOM.createRoot) {
// @ts-ignore react 18 typings
hydrated.current.render(null)
} else {
ReactDOM.render(null as unknown as ReactElement, root.current)
}
reactRender(
null as unknown as ReactElement,
root.current,
reactRootRef.current
)
}
}
}
4 changes: 4 additions & 0 deletions packages/gatsby-plugin-image/src/gatsby-node.ts
Expand Up @@ -5,6 +5,7 @@ import {
ImageLayoutType,
ImagePlaceholderType,
} from "./resolver-utils"
import { major } from "semver"

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

Expand Down Expand Up @@ -51,6 +52,9 @@ export const onCreateWebpackConfig: GatsbyNode["onCreateWebpackConfig"] = ({
plugins.define({
// eslint-disable-next-line @typescript-eslint/naming-convention
GATSBY___IMAGE: true,
HAS_REACT_18: JSON.stringify(
major(require(`react-dom/package.json`).version) >= 18
),
}),
],
})
Expand Down
1 change: 1 addition & 0 deletions packages/gatsby-plugin-image/src/global.d.ts
Expand Up @@ -3,4 +3,5 @@ export {}
declare global {
declare var SERVER: boolean | undefined
declare var GATSBY___IMAGE: boolean | undefined
declare var HAS_REACT_18: boolean | undefined
}
4 changes: 2 additions & 2 deletions packages/gatsby-plugin-jss/package.json
Expand Up @@ -26,8 +26,8 @@
"main": "index.js",
"peerDependencies": {
"gatsby": "^4.0.0-next",
"react": "^16.9.0 || ^17.0.0",
"react-dom": "^16.9.0 || ^17.0.0"
"react": "^16.9.0 || ^17.0.0 || ^18.0.0",
"react-dom": "^16.9.0 || ^17.0.0 || ^18.0.0"
},
"repository": {
"type": "git",
Expand Down
4 changes: 2 additions & 2 deletions packages/gatsby-plugin-mdx/package.json
Expand Up @@ -17,8 +17,8 @@
"@mdx-js/mdx": "^1.0.0",
"@mdx-js/react": "^1.0.0",
"gatsby": "^4.0.0-next",
"react": "^16.9.0 || ^17.0.0",
"react-dom": "^16.9.0 || ^17.0.0"
"react": "^16.9.0 || ^17.0.0 || ^18.0.0",
"react-dom": "^16.9.0 || ^17.0.0 || ^18.0.0"
},
"dependencies": {
"@babel/core": "^7.15.5",
Expand Down
4 changes: 2 additions & 2 deletions packages/gatsby-plugin-netlify-cms/package.json
Expand Up @@ -38,8 +38,8 @@
"peerDependencies": {
"gatsby": "^4.0.0-next",
"netlify-cms-app": "^2.9.0",
"react": "^16.9.0 || ^17.0.0",
"react-dom": "^16.9.0 || ^17.0.0",
"react": "^16.9.0 || ^17.0.0 || ^18.0.0",
"react-dom": "^16.9.0 || ^17.0.0 || ^18.0.0",
"webpack": "^5.0.0"
},
"repository": {
Expand Down

0 comments on commit 0c61265

Please sign in to comment.