Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 9c4a46d

Browse files
authored
feat: Add support for React 19 Canary (#1294)
1 parent 4e10ba3 commit 9c4a46d

File tree

8 files changed

+96
-46
lines changed

8 files changed

+96
-46
lines changed

‎.github/workflows/validate.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ jobs:
3030
fail-fast: false
3131
matrix:
3232
node: [14, 16, 18]
33-
react: [latest, canary, experimental]
33+
react: ['18.x', latest, canary, experimental]
3434
runs-on: ubuntu-latest
3535
steps:
3636
- name: ⬇️ Checkout repo

‎jest.config.js‎

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,17 @@ const {jest: jestConfig} = require('kcd-scripts/config')
33
module.exports = Object.assign(jestConfig, {
44
coverageThreshold: {
55
...jestConfig.coverageThreshold,
6-
// Full coverage across the build matrix (React versions) but not in a single job
6+
// Full coverage across the build matrix (React 18, 19) but not in a single job
77
// Ful coverage is checked via codecov
8-
'./src/pure.js': {
9-
// minimum coverage of jobs using different React versions
10-
branches: 97,
8+
'./src/act-compat': {
9+
branches: 90,
10+
},
11+
'./src/pure': {
12+
// minimum coverage of jobs using React 18 and 19
13+
branches: 95,
1114
functions: 88,
12-
lines: 94,
13-
statements: 94,
15+
lines: 92,
16+
statements: 92,
1417
},
1518
},
1619
})

‎src/__tests__/new-act.js‎

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
let asyncAct
22

3-
jest.mock('react-dom/test-utils', () => ({
4-
act: cb => {
5-
return cb()
6-
},
7-
}))
3+
jest.mock('react', () => {
4+
return {
5+
...jest.requireActual('react'),
6+
act: cb => {
7+
return cb()
8+
},
9+
}
10+
})
811

912
beforeEach(() => {
1013
jest.resetModules()

‎src/__tests__/render.js‎

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,11 @@ import ReactDOM from 'react-dom'
33
import ReactDOMServer from 'react-dom/server'
44
import {fireEvent, render, screen, configure} from '../'
55

6-
// Needs to be changed to 19.0.0 once alpha started.
7-
const isReactExperimental = React.version.startsWith('18.3.0-experimental')
8-
const isReactCanary = React.version.startsWith('18.3.0-canary')
6+
const isReact18 = React.version.startsWith('18.')
7+
const isReact19 = React.version.startsWith('19.')
98

10-
// Needs to be changed to isReactExperimental || isReactCanary once alpha started.
11-
const testGateReact18 = isReactExperimental ? test.skip : test
9+
consttestGateReact18=isReact18 ? test : test.skip
10+
const testGateReact19 = isReact19 ? test : test.skip
1211

1312
describe('render API', () => {
1413
let originalConfig
@@ -224,32 +223,43 @@ describe('render API', () => {
224223
expect(() => {
225224
render(<div />, {legacyRoot: true})
226225
}).toErrorDev(
227-
isReactCanary
228-
? [
229-
"Warning: ReactDOM.render is no longer supported in React 18. Use createRoot instead. Until you switch to the new API, your app will behave as if it's running React 17. Learn more: https://react.dev/link/switch-to-createroot",
230-
]
231-
: [
232-
"Warning: ReactDOM.render is no longer supported in React 18. Use createRoot instead. Until you switch to the new API, your app will behave as if it's running React 17. Learn more: https://reactjs.org/link/switch-to-createroot",
233-
],
226+
[
227+
"Warning: ReactDOM.render is no longer supported in React 18. Use createRoot instead. Until you switch to the new API, your app will behave as if it's running React 17. Learn more: https://reactjs.org/link/switch-to-createroot",
228+
],
234229
{withoutStack: true},
235230
)
236231
})
237232

233+
testGateReact19('legacyRoot throws', () => {
234+
expect(() => {
235+
render(<div />, {legacyRoot: true})
236+
}).toThrowErrorMatchingInlineSnapshot(
237+
`\`legacyRoot: true\` is not supported in this version of React. Please use React 18 instead.`,
238+
)
239+
})
240+
238241
testGateReact18('legacyRoot uses legacy ReactDOM.hydrate', () => {
239242
const ui = <div />
240243
const container = document.createElement('div')
241244
container.innerHTML = ReactDOMServer.renderToString(ui)
242245
expect(() => {
243246
render(ui, {container, hydrate: true, legacyRoot: true})
244247
}).toErrorDev(
245-
isReactCanary
246-
? [
247-
"Warning: ReactDOM.hydrate is no longer supported in React 18. Use hydrateRoot instead. Until you switch to the new API, your app will behave as if it's running React 17. Learn more: https://react.dev/link/switch-to-createroot",
248-
]
249-
: [
250-
"Warning: ReactDOM.hydrate is no longer supported in React 18. Use hydrateRoot instead. Until you switch to the new API, your app will behave as if it's running React 17. Learn more: https://reactjs.org/link/switch-to-createroot",
251-
],
248+
[
249+
"Warning: ReactDOM.hydrate is no longer supported in React 18. Use hydrateRoot instead. Until you switch to the new API, your app will behave as if it's running React 17. Learn more: https://reactjs.org/link/switch-to-createroot",
250+
],
252251
{withoutStack: true},
253252
)
254253
})
254+
255+
testGateReact19('legacyRoot throws even with hydrate', () => {
256+
const ui = <div />
257+
const container = document.createElement('div')
258+
container.innerHTML = ReactDOMServer.renderToString(ui)
259+
expect(() => {
260+
render(ui, {container, hydrate: true, legacyRoot: true})
261+
}).toThrowErrorMatchingInlineSnapshot(
262+
`\`legacyRoot: true\` is not supported in this version of React. Please use React 18 instead.`,
263+
)
264+
})
255265
})

‎src/__tests__/renderHook.js‎

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
import React from 'react'
22
import {renderHook} from '../pure'
33

4-
// Needs to be changed to 19.0.0 once alpha started.
5-
const isReactExperimental = React.version.startsWith('18.3.0-experimental')
6-
const isReactCanary = React.version.startsWith('18.3.0')
4+
const isReact18 = React.version.startsWith('18.')
5+
const isReact19 = React.version.startsWith('19.')
76

8-
// Needs to be changed to isReactExperimental || isReactCanary once alpha started.
9-
const testGateReact18 = isReactExperimental ? test.skip : test
7+
consttestGateReact18=isReact18 ? test : test.skip
8+
const testGateReact19 = isReact19 ? test : test.skip
109

1110
test('gives committed result', () => {
1211
const {result} = renderHook(() => {
@@ -85,14 +84,30 @@ testGateReact18('legacyRoot uses legacy ReactDOM.render', () => {
8584
},
8685
).result
8786
}).toErrorDev(
88-
isReactCanary
89-
? [
90-
"Warning: ReactDOM.render is no longer supported in React 18. Use createRoot instead. Until you switch to the new API, your app will behave as if it's running React 17. Learn more: https://react.dev/link/switch-to-createroot",
91-
]
92-
: [
93-
"Warning: ReactDOM.render is no longer supported in React 18. Use createRoot instead. Until you switch to the new API, your app will behave as if it's running React 17. Learn more: https://reactjs.org/link/switch-to-createroot",
94-
],
87+
[
88+
"Warning: ReactDOM.render is no longer supported in React 18. Use createRoot instead. Until you switch to the new API, your app will behave as if it's running React 17. Learn more: https://reactjs.org/link/switch-to-createroot",
89+
],
9590
{withoutStack: true},
9691
)
9792
expect(result.current).toEqual('provided')
9893
})
94+
95+
testGateReact19('legacyRoot throws', () => {
96+
const Context = React.createContext('default')
97+
function Wrapper({children}) {
98+
return <Context.Provider value="provided">{children}</Context.Provider>
99+
}
100+
expect(() => {
101+
renderHook(
102+
() => {
103+
return React.useContext(Context)
104+
},
105+
{
106+
wrapper: Wrapper,
107+
legacyRoot: true,
108+
},
109+
).result
110+
}).toThrowErrorMatchingInlineSnapshot(
111+
`\`legacyRoot: true\` is not supported in this version of React. Please use React 18 instead.`,
112+
)
113+
})

‎src/act-compat.js‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
import * as testUtils from 'react-dom/test-utils'
1+
import * as React from 'react'
2+
import * as DeprecatedReactTestUtils from 'react-dom/test-utils'
23

3-
const domAct = testUtils.act
4+
const reactAct = React.act??DeprecatedReactTestUtils.act
45

56
function getGlobalThis() {
67
/* istanbul ignore else */
@@ -78,7 +79,7 @@ function withGlobalActEnvironment(actImplementation) {
7879
}
7980
}
8081

81-
const act = withGlobalActEnvironment(domAct)
82+
const act = withGlobalActEnvironment(reactAct)
8283

8384
export default act
8485
export {

‎src/pure.js‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,14 @@ function render(
207207
wrapper,
208208
} = {},
209209
) {
210+
if (legacyRoot && typeof ReactDOM.render !== 'function') {
211+
const error = new Error(
212+
'`legacyRoot: true` is not supported in this version of React. Please use React 18 instead.',
213+
)
214+
Error.captureStackTrace(error, render)
215+
throw error
216+
}
217+
210218
if (!baseElement) {
211219
// default to document.body instead of documentElement to avoid output of potentially-large
212220
// head elements (such as JSS style blocks) in debug output
@@ -263,6 +271,15 @@ function cleanup() {
263271

264272
function renderHook(renderCallback, options = {}) {
265273
const {initialProps, ...renderOptions} = options
274+
275+
if (renderOptions.legacyRoot && typeof ReactDOM.render !== 'function') {
276+
const error = new Error(
277+
'`legacyRoot: true` is not supported in this version of React. Please use React 18 instead.',
278+
)
279+
Error.captureStackTrace(error, renderHook)
280+
throw error
281+
}
282+
266283
const result = React.createRef()
267284

268285
function TestComponent({renderCallbackProps}) {

‎types/index.d.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ export interface RenderOptions<
7373
*/
7474
hydrate?: boolean
7575
/**
76+
* Only works if used with React 18.
7677
* Set to `true` if you want to force synchronous `ReactDOM.render`.
7778
* Otherwise `render` will default to concurrent React if available.
7879
*/

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /