Skip to content

Commit e8ec52b

Browse files
author
Sebastian Silbermann
committed
Remove support for legacy root
1 parent aabdfda commit e8ec52b

File tree

4 files changed

+28
-136
lines changed

4 files changed

+28
-136
lines changed

src/__tests__/render.js

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -212,29 +212,4 @@ describe('render API', () => {
212212

213213
expect(wrapperComponentMountEffect).toHaveBeenCalledTimes(1)
214214
})
215-
216-
test('legacyRoot uses legacy ReactDOM.render', () => {
217-
expect(() => {
218-
render(<div />, {legacyRoot: true})
219-
}).toErrorDev(
220-
[
221-
"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",
222-
],
223-
{withoutStack: true},
224-
)
225-
})
226-
227-
test('legacyRoot uses legacy ReactDOM.hydrate', () => {
228-
const ui = <div />
229-
const container = document.createElement('div')
230-
container.innerHTML = ReactDOMServer.renderToString(ui)
231-
expect(() => {
232-
render(ui, {container, hydrate: true, legacyRoot: true})
233-
}).toErrorDev(
234-
[
235-
"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",
236-
],
237-
{withoutStack: true},
238-
)
239-
})
240215
})

src/__tests__/renderHook.js

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -60,28 +60,3 @@ test('allows wrapper components', async () => {
6060

6161
expect(result.current).toEqual('provided')
6262
})
63-
64-
test('legacyRoot uses legacy ReactDOM.render', () => {
65-
const Context = React.createContext('default')
66-
function Wrapper({children}) {
67-
return <Context.Provider value="provided">{children}</Context.Provider>
68-
}
69-
let result
70-
expect(() => {
71-
result = renderHook(
72-
() => {
73-
return React.useContext(Context)
74-
},
75-
{
76-
wrapper: Wrapper,
77-
legacyRoot: true,
78-
},
79-
).result
80-
}).toErrorDev(
81-
[
82-
"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",
83-
],
84-
{withoutStack: true},
85-
)
86-
expect(result.current).toEqual('provided')
87-
})

src/pure.js

Lines changed: 26 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import * as React from 'react'
2-
import ReactDOM from 'react-dom'
32
import * as ReactDOMClient from 'react-dom/client'
43
import {
54
getQueriesForElement,
@@ -73,7 +72,7 @@ configureDTL({
7372
*/
7473
const mountedContainers = new Set()
7574
/**
76-
* @type Array<{container: import('react-dom').Container, root: ReturnType<typeof createConcurrentRoot>}>
75+
* @type Array<{container: import('react-dom').Container, root: ReturnType<typeof createTestRoot>}>
7776
*/
7877
const mountedRootEntries = []
7978

@@ -89,73 +88,10 @@ function wrapUiIfNeeded(innerElement, wrapperComponent) {
8988
: innerElement
9089
}
9190

92-
function createConcurrentRoot(
93-
container,
94-
{hydrate, ui, wrapper: WrapperComponent},
95-
) {
96-
let root
97-
if (hydrate) {
98-
act(() => {
99-
root = ReactDOMClient.hydrateRoot(
100-
container,
101-
strictModeIfNeeded(wrapUiIfNeeded(ui, WrapperComponent)),
102-
)
103-
})
104-
} else {
105-
root = ReactDOMClient.createRoot(container)
106-
}
107-
108-
return {
109-
hydrate() {
110-
/* istanbul ignore if */
111-
if (!hydrate) {
112-
throw new Error(
113-
'Attempted to hydrate a non-hydrateable root. This is a bug in `@testing-library/react`.',
114-
)
115-
}
116-
// Nothing to do since hydration happens when creating the root object.
117-
},
118-
render(element) {
119-
root.render(element)
120-
},
121-
unmount() {
122-
root.unmount()
123-
},
124-
}
125-
}
126-
127-
function createLegacyRoot(container) {
128-
return {
129-
hydrate(element) {
130-
ReactDOM.hydrate(element, container)
131-
},
132-
render(element) {
133-
ReactDOM.render(element, container)
134-
},
135-
unmount() {
136-
ReactDOM.unmountComponentAtNode(container)
137-
},
138-
}
139-
}
140-
141-
function renderRoot(
91+
function createTestView(
14292
ui,
143-
{baseElement, container, hydrate, queries, root, wrapper: WrapperComponent},
93+
{baseElement, container, queries, root, WrapperComponent},
14494
) {
145-
act(() => {
146-
if (hydrate) {
147-
root.hydrate(
148-
strictModeIfNeeded(wrapUiIfNeeded(ui, WrapperComponent)),
149-
container,
150-
)
151-
} else {
152-
root.render(
153-
strictModeIfNeeded(wrapUiIfNeeded(ui, WrapperComponent)),
154-
container,
155-
)
156-
}
157-
})
158-
15995
return {
16096
container,
16197
baseElement,
@@ -171,11 +107,10 @@ function renderRoot(
171107
})
172108
},
173109
rerender: rerenderUi => {
174-
renderRoot(rerenderUi, {
175-
container,
176-
baseElement,
177-
root,
178-
wrapper: WrapperComponent,
110+
act(() => {
111+
root.render(
112+
strictModeIfNeeded(wrapUiIfNeeded(rerenderUi, WrapperComponent)),
113+
)
179114
})
180115
// Intentionally do not return anything to avoid unnecessarily complicating the API.
181116
// folks can use all the same utilities we return in the first place that are bound to the container
@@ -201,10 +136,9 @@ function render(
201136
{
202137
container,
203138
baseElement = container,
204-
legacyRoot = false,
205139
queries,
206140
hydrate = false,
207-
wrapper,
141+
wrapper: WrapperComponent,
208142
} = {},
209143
) {
210144
if (!baseElement) {
@@ -219,8 +153,16 @@ function render(
219153
let root
220154
// eslint-disable-next-line no-negated-condition -- we want to map the evolution of this over time. The root is created first. Only later is it re-used so we don't want to read the case that happens later first.
221155
if (!mountedContainers.has(container)) {
222-
const createRootImpl = legacyRoot ? createLegacyRoot : createConcurrentRoot
223-
root = createRootImpl(container, {hydrate, ui, wrapper})
156+
if (hydrate) {
157+
act(() => {
158+
root = ReactDOMClient.hydrateRoot(
159+
container,
160+
strictModeIfNeeded(wrapUiIfNeeded(ui, WrapperComponent)),
161+
)
162+
})
163+
} else {
164+
root = ReactDOMClient.createRoot(container)
165+
}
224166

225167
mountedRootEntries.push({container, root})
226168
// we'll add it to the mounted containers regardless of whether it's actually
@@ -238,12 +180,17 @@ function render(
238180
})
239181
}
240182

241-
return renderRoot(ui, {
183+
if (!hydrate) {
184+
act(() => {
185+
root.render(strictModeIfNeeded(wrapUiIfNeeded(ui, WrapperComponent)))
186+
})
187+
}
188+
189+
return createTestView(ui, {
242190
container,
243191
baseElement,
244192
queries,
245-
hydrate,
246-
wrapper,
193+
WrapperComponent,
247194
root,
248195
})
249196
}

types/index.d.ts

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -67,17 +67,12 @@ export interface RenderOptions<
6767
*/
6868
baseElement?: BaseElement
6969
/**
70-
* If `hydrate` is set to `true`, then it will render with `ReactDOM.hydrate`. This may be useful if you are using server-side
71-
* rendering and use ReactDOM.hydrate to mount your components.
70+
* If `hydrate` is set to `true`, then it will create a root with `ReactDOMClient.hydrateRoot`. This may be useful if you are using server-side
71+
* rendering and use ReactDOMClient.hydrateRoot to mount your components.
7272
*
7373
* @see https://testing-library.com/docs/react-testing-library/api/#hydrate)
7474
*/
7575
hydrate?: boolean
76-
/**
77-
* Set to `true` if you want to force synchronous `ReactDOM.render`.
78-
* Otherwise `render` will default to concurrent React if available.
79-
*/
80-
legacyRoot?: boolean
8176
/**
8277
* Queries to bind. Overrides the default set from DOM Testing Library unless merged.
8378
*

0 commit comments

Comments
 (0)