@@ -15,6 +15,7 @@ import type {FrontendBridge} from 'react-devtools-shared/src/bridge';
15
15
import type Store from 'react-devtools-shared/src/devtools/store' ;
16
16
import type { ProfilingDataFrontend } from 'react-devtools-shared/src/devtools/views/Profiler/types' ;
17
17
import type { ElementType } from 'react-devtools-shared/src/frontend/types' ;
18
+ import type { Node as ReactNode } from 'react' ;
18
19
19
20
import { ReactVersion } from '../../../../ReactVersions' ;
20
21
@@ -99,6 +100,127 @@ export async function actAsync(
99
100
}
100
101
}
101
102
103
+ type RenderImplementation = {
104
+ render : ( elements : ?ReactNode ) => ( ) => void ,
105
+ unmount : ( ) => void ,
106
+ createContainer : ( ) => void ,
107
+ getContainer : ( ) => ?HTMLElement ,
108
+ } ;
109
+
110
+ export function getLegacyRenderImplementation ( ) : RenderImplementation {
111
+ let ReactDOM ;
112
+ let container ;
113
+ let containersToRemove = [ ] ;
114
+
115
+ beforeEach ( ( ) => {
116
+ ReactDOM = require ( 'react-dom' ) ;
117
+
118
+ createContainer ( ) ;
119
+ } ) ;
120
+
121
+ afterEach ( ( ) => {
122
+ containersToRemove . forEach ( container =>
123
+ document . body . removeChild ( container ) ,
124
+ ) ;
125
+ containersToRemove . splice ( 0 , containersToRemove . length ) ;
126
+
127
+ ReactDOM = null ;
128
+ container = null ;
129
+ } ) ;
130
+
131
+ function render ( elements ) {
132
+ withErrorsOrWarningsIgnored (
133
+ [ 'ReactDOM.render is no longer supported in React 18' ] ,
134
+ ( ) => {
135
+ ReactDOM . render ( elements , container ) ;
136
+ } ,
137
+ ) ;
138
+
139
+ return unmount ;
140
+ }
141
+
142
+ function unmount ( ) {
143
+ ReactDOM . unmountComponentAtNode ( container ) ;
144
+ }
145
+
146
+ function createContainer ( ) {
147
+ container = document . createElement ( 'div' ) ;
148
+ document . body . appendChild ( container ) ;
149
+
150
+ containersToRemove . push ( container ) ;
151
+ }
152
+
153
+ function getContainer ( ) {
154
+ return container ;
155
+ }
156
+
157
+ return {
158
+ render,
159
+ unmount,
160
+ createContainer,
161
+ getContainer,
162
+ } ;
163
+ }
164
+
165
+ export function getModernRenderImplementation ( ) : RenderImplementation {
166
+ let ReactDOMClient ;
167
+ let container ;
168
+ let root ;
169
+ let containersToRemove = [ ] ;
170
+
171
+ beforeEach ( ( ) => {
172
+ ReactDOMClient = require ( 'react-dom/client' ) ;
173
+
174
+ createContainer ( ) ;
175
+ } ) ;
176
+
177
+ afterEach ( ( ) => {
178
+ containersToRemove . forEach ( container =>
179
+ document . body . removeChild ( container ) ,
180
+ ) ;
181
+ containersToRemove . splice ( 0 , containersToRemove . length ) ;
182
+
183
+ ReactDOMClient = null ;
184
+ container = null ;
185
+ root = null ;
186
+ } ) ;
187
+
188
+ function render ( elements ) {
189
+ root . render ( elements ) ;
190
+
191
+ return unmount ;
192
+ }
193
+
194
+ function unmount ( ) {
195
+ root . unmount ( ) ;
196
+ }
197
+
198
+ function createContainer ( ) {
199
+ container = document . createElement ( 'div' ) ;
200
+ document . body . appendChild ( container ) ;
201
+
202
+ root = ReactDOMClient . createRoot ( container ) ;
203
+
204
+ containersToRemove . push ( container ) ;
205
+ }
206
+
207
+ function getContainer ( ) {
208
+ return container ;
209
+ }
210
+
211
+ return {
212
+ render,
213
+ unmount,
214
+ createContainer,
215
+ getContainer,
216
+ } ;
217
+ }
218
+
219
+ export const getVersionedRenderImplementation : ( ) => RenderImplementation =
220
+ semver . lt ( requestedReactVersion , '18.0.0' )
221
+ ? getLegacyRenderImplementation
222
+ : getModernRenderImplementation ;
223
+
102
224
export function beforeEachProfiling ( ) : void {
103
225
// Mock React's timing information so that test runs are predictable.
104
226
jest . mock ( 'scheduler' , ( ) => jest . requireActual ( 'scheduler/unstable_mock' ) ) ;
0 commit comments