remove unstable_renderSubtreeIntoContainer (#29771)
remove unstable_renderSubtreeIntoContainer This is finally no longer used and can be deleted.
Jan Kassens committed
Jun 12, 2024 at 11:14 UTC
93826c8483ffaf6676c437c25619d82f13444413
5 files changed
+1
-429
packages/react-dom/src/ReactDOMFB.js
-1
@@ -43,6 +43,5 @@ export {
43
render,
44
unstable_batchedUpdates,
45
findDOMNode,
46
- unstable_renderSubtreeIntoContainer,
46
unmountComponentAtNode,
47
} from './client/ReactDOMRootFB';
packages/react-dom/src/__tests__/renderSubtreeIntoContainer-test.js
deleted
-353
@@ -1,353 +0,0 @@
1
-/**
2
- * Copyright (c) Meta Platforms, Inc. and affiliates.
3
- *
4
- * This source code is licensed under the MIT license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- *
7
- * @emails react-core
8
- */
9
-
10
-'use strict';
11
-
12
-const React = require('react');
13
-const PropTypes = require('prop-types');
14
-const ReactDOM = require('react-dom');
15
-const ReactDOMClient = require('react-dom/client');
16
-const act = require('internal-test-utils').act;
17
-const renderSubtreeIntoContainer =
18
- require('react-dom').unstable_renderSubtreeIntoContainer;
19
-
20
-describe('renderSubtreeIntoContainer', () => {
21
- // @gate !disableLegacyContext
22
- // @gate !disableLegacyMode
23
- it('should pass context when rendering subtree elsewhere', () => {
24
- const portal = document.createElement('div');
25
-
26
- class Component extends React.Component {
27
- static contextTypes = {
28
- foo: PropTypes.string.isRequired,
29
- };
30
-
31
- render() {
32
- return <div>{this.context.foo}</div>;
33
- }
34
- }
35
-
36
- class Parent extends React.Component {
37
- static childContextTypes = {
38
- foo: PropTypes.string.isRequired,
39
- };
40
-
41
- getChildContext() {
42
- return {
43
- foo: 'bar',
44
- };
45
- }
46
-
47
- render() {
48
- return null;
49
- }
50
-
51
- componentDidMount() {
52
- expect(
53
- function () {
54
- renderSubtreeIntoContainer(this, <Component />, portal);
55
- }.bind(this),
56
- ).toErrorDev(
57
- 'ReactDOM.unstable_renderSubtreeIntoContainer() has not been supported since React 18',
58
- );
59
- }
60
- }
61
-
62
- const container = document.createElement('div');
63
- ReactDOM.render(<Parent />, container);
64
- expect(portal.firstChild.innerHTML).toBe('bar');
65
- });
66
-
67
- // @gate !disableLegacyContext
68
- // @gate !disableLegacyMode
69
- it('should update context if it changes due to setState', async () => {
70
- const container = document.createElement('div');
71
- document.body.appendChild(container);
72
- const portal = document.createElement('div');
73
-
74
- class Component extends React.Component {
75
- static contextTypes = {
76
- foo: PropTypes.string.isRequired,
77
- getFoo: PropTypes.func.isRequired,
78
- };
79
-
80
- render() {
81
- return <div>{this.context.foo + '-' + this.context.getFoo()}</div>;
82
- }
83
- }
84
-
85
- class Parent extends React.Component {
86
- static childContextTypes = {
87
- foo: PropTypes.string.isRequired,
88
- getFoo: PropTypes.func.isRequired,
89
- };
90
-
91
- state = {
92
- bar: 'initial',
93
- };
94
-
95
- getChildContext() {
96
- return {
97
- foo: this.state.bar,
98
- getFoo: () => this.state.bar,
99
- };
100
- }
101
-
102
- render() {
103
- return null;
104
- }
105
-
106
- componentDidMount() {
107
- expect(() => {
108
- renderSubtreeIntoContainer(this, <Component />, portal);
109
- }).toErrorDev(
110
- 'ReactDOM.unstable_renderSubtreeIntoContainer() has not been supported since React 18',
111
- );
112
- }
113
-
114
- componentDidUpdate() {
115
- expect(() => {
116
- renderSubtreeIntoContainer(this, <Component />, portal);
117
- }).toErrorDev(
118
- 'ReactDOM.unstable_renderSubtreeIntoContainer() has not been supported since React 18',
119
- );
120
- }
121
- }
122
- const root = ReactDOMClient.createRoot(container);
123
- const parentRef = React.createRef();
124
- await act(async () => {
125
- root.render(<Parent ref={parentRef} />);
126
- });
127
- const instance = parentRef.current;
128
-
129
- expect(portal.firstChild.innerHTML).toBe('initial-initial');
130
- await act(async () => {
131
- instance.setState({bar: 'changed'});
132
- });
133
- expect(portal.firstChild.innerHTML).toBe('changed-changed');
134
- });
135
-
136
- // @gate !disableLegacyContext
137
- // @gate !disableLegacyMode
138
- it('should update context if it changes due to re-render', async () => {
139
- const container = document.createElement('div');
140
- document.body.appendChild(container);
141
- const portal = document.createElement('div');
142
-
143
- class Component extends React.Component {
144
- static contextTypes = {
145
- foo: PropTypes.string.isRequired,
146
- getFoo: PropTypes.func.isRequired,
147
- };
148
-
149
- render() {
150
- return <div>{this.context.foo + '-' + this.context.getFoo()}</div>;
151
- }
152
- }
153
-
154
- class Parent extends React.Component {
155
- static childContextTypes = {
156
- foo: PropTypes.string.isRequired,
157
- getFoo: PropTypes.func.isRequired,
158
- };
159
-
160
- getChildContext() {
161
- return {
162
- foo: this.props.bar,
163
- getFoo: () => this.props.bar,
164
- };
165
- }
166
-
167
- render() {
168
- return null;
169
- }
170
-
171
- componentDidMount() {
172
- expect(() => {
173
- renderSubtreeIntoContainer(this, <Component />, portal);
174
- }).toErrorDev(
175
- 'ReactDOM.unstable_renderSubtreeIntoContainer() has not been supported since React 18',
176
- );
177
- }
178
-
179
- componentDidUpdate() {
180
- expect(() => {
181
- renderSubtreeIntoContainer(this, <Component />, portal);
182
- }).toErrorDev(
183
- 'ReactDOM.unstable_renderSubtreeIntoContainer() has not been supported since React 18',
184
- );
185
- }
186
- }
187
-
188
- const root = ReactDOMClient.createRoot(container);
189
- await act(async () => {
190
- root.render(<Parent bar="initial" />);
191
- });
192
- expect(portal.firstChild.innerHTML).toBe('initial-initial');
193
- await act(async () => {
194
- root.render(<Parent bar="changed" />);
195
- });
196
- expect(portal.firstChild.innerHTML).toBe('changed-changed');
197
- });
198
-
199
- // @gate !disableLegacyMode
200
- it('should render portal with non-context-provider parent', async () => {
201
- const container = document.createElement('div');
202
- document.body.appendChild(container);
203
- const portal = document.createElement('div');
204
-
205
- class Parent extends React.Component {
206
- render() {
207
- return null;
208
- }
209
-
210
- componentDidMount() {
211
- expect(() => {
212
- renderSubtreeIntoContainer(this, <div>hello</div>, portal);
213
- }).toErrorDev(
214
- 'ReactDOM.unstable_renderSubtreeIntoContainer() has not been supported since React 18',
215
- );
216
- }
217
- }
218
-
219
- const root = ReactDOMClient.createRoot(container);
220
- await act(async () => {
221
- root.render(<Parent bar="initial" />);
222
- });
223
- expect(portal.firstChild.innerHTML).toBe('hello');
224
- });
225
-
226
- // @gate !disableLegacyContext
227
- // @gate !disableLegacyMode
228
- it('should get context through non-context-provider parent', async () => {
229
- const container = document.createElement('div');
230
- document.body.appendChild(container);
231
- const portal = document.createElement('div');
232
-
233
- class Parent extends React.Component {
234
- render() {
235
- return <Middle />;
236
- }
237
- getChildContext() {
238
- return {value: this.props.value};
239
- }
240
- static childContextTypes = {
241
- value: PropTypes.string.isRequired,
242
- };
243
- }
244
-
245
- class Middle extends React.Component {
246
- render() {
247
- return null;
248
- }
249
- componentDidMount() {
250
- expect(() => {
251
- renderSubtreeIntoContainer(this, <Child />, portal);
252
- }).toErrorDev(
253
- 'ReactDOM.unstable_renderSubtreeIntoContainer() has not been supported since React 18',
254
- );
255
- }
256
- }
257
-
258
- class Child extends React.Component {
259
- static contextTypes = {
260
- value: PropTypes.string.isRequired,
261
- };
262
- render() {
263
- return <div>{this.context.value}</div>;
264
- }
265
- }
266
-
267
- const root = ReactDOMClient.createRoot(container);
268
- await act(async () => {
269
- root.render(<Parent value="foo" />);
270
- });
271
- expect(portal.textContent).toBe('foo');
272
- });
273
-
274
- // @gate !disableLegacyContext
275
- // @gate !disableLegacyMode
276
- it('should get context through middle non-context-provider layer', async () => {
277
- const container = document.createElement('div');
278
- document.body.appendChild(container);
279
- const portal1 = document.createElement('div');
280
- const portal2 = document.createElement('div');
281
-
282
- class Parent extends React.Component {
283
- render() {
284
- return null;
285
- }
286
- getChildContext() {
287
- return {value: this.props.value};
288
- }
289
- componentDidMount() {
290
- expect(() => {
291
- renderSubtreeIntoContainer(this, <Middle />, portal1);
292
- }).toErrorDev(
293
- 'ReactDOM.unstable_renderSubtreeIntoContainer() has not been supported since React 18',
294
- );
295
- }
296
- static childContextTypes = {
297
- value: PropTypes.string.isRequired,
298
- };
299
- }
300
-
301
- class Middle extends React.Component {
302
- render() {
303
- return null;
304
- }
305
- componentDidMount() {
306
- expect(() => {
307
- renderSubtreeIntoContainer(this, <Child />, portal2);
308
- }).toErrorDev(
309
- 'ReactDOM.unstable_renderSubtreeIntoContainer() has not been supported since React 18',
310
- );
311
- }
312
- }
313
-
314
- class Child extends React.Component {
315
- static contextTypes = {
316
- value: PropTypes.string.isRequired,
317
- };
318
- render() {
319
- return <div>{this.context.value}</div>;
320
- }
321
- }
322
-
323
- const root = ReactDOMClient.createRoot(container);
324
- await act(async () => {
325
- root.render(<Parent value="foo" />);
326
- });
327
- expect(portal2.textContent).toBe('foo');
328
- });
329
-
330
- // @gate !disableLegacyMode
331
- it('legacy test: fails gracefully when mixing React 15 and 16', () => {
332
- class C extends React.Component {
333
- render() {
334
- return <div />;
335
- }
336
- }
337
- const c = ReactDOM.render(<C />, document.createElement('div'));
338
- // React 15 calls this:
339
- // https://github.com/facebook/react/blob/77b71fc3c4/src/renderers/dom/client/ReactMount.js#L478-L479
340
- expect(() => {
341
- c._reactInternalInstance._processChildContext({});
342
- }).toThrow(
343
- __DEV__
344
- ? '_processChildContext is not available in React 16+. This likely ' +
345
- 'means you have multiple copies of React and are attempting to nest ' +
346
- 'a React 15 tree inside a React 16 tree using ' +
347
- "unstable_renderSubtreeIntoContainer, which isn't supported. Try to " +
348
- 'make sure you have only one copy of React (and ideally, switch to ' +
349
- 'ReactDOM.createPortal).'
350
- : "Cannot read property '_processChildContext' of undefined",
351
- );
352
- });
353
-});
packages/react-dom/src/client/ReactDOMRootFB.js
-41
@@ -59,7 +59,6 @@ import {
59
} from 'react-reconciler/src/ReactFiberReconciler';
60
import {LegacyRoot} from 'react-reconciler/src/ReactRootTags';
61
import getComponentNameFromType from 'shared/getComponentNameFromType';
62
-import {has as hasInstance} from 'shared/ReactInstanceMap';
62
63
import {
64
current as currentOwner,
@@ -420,46 +419,6 @@ export function render(
419
);
420
}
421
423
-export function unstable_renderSubtreeIntoContainer(
424
- parentComponent: React$Component<any, any>,
425
- element: React$Element<any>,
426
- containerNode: Container,
427
- callback: ?Function,
428
-): React$Component<any, any> | PublicInstance | null {
429
- if (disableLegacyMode) {
430
- if (__DEV__) {
431
- console.error(
432
- 'ReactDOM.unstable_renderSubtreeIntoContainer() was removed in React 19. Consider using a portal instead.',
433
- );
434
- }
435
- throw new Error('ReactDOM: Unsupported Legacy Mode API.');
436
- }
437
- if (__DEV__) {
438
- console.error(
439
- 'ReactDOM.unstable_renderSubtreeIntoContainer() has not been supported ' +
440
- 'since React 18. Consider using a portal instead. Until you switch to ' +
441
- "the createRoot API, your app will behave as if it's running React " +
442
- '17. Learn more: https://react.dev/link/switch-to-createroot',
443
- );
444
- }
445
-
446
- if (!isValidContainerLegacy(containerNode)) {
447
- throw new Error('Target container is not a DOM element.');
448
- }
449
-
450
- if (parentComponent == null || !hasInstance(parentComponent)) {
451
- throw new Error('parentComponent must be a valid React Component');
452
- }
453
-
454
- return legacyRenderSubtreeIntoContainer(
455
- parentComponent,
456
- element,
457
- containerNode,
458
- false,
459
- callback,
460
- );
461
-}
462
-
422
export function unmountComponentAtNode(container: Container): boolean {
423
if (disableLegacyMode) {
424
if (__DEV__) {
packages/react-reconciler/src/ReactFiberClassComponent.js
+1
-21
@@ -73,9 +73,7 @@ import {
73
setIsStrictModeForDevtools,
74
} from './ReactFiberDevToolsHook';
75
76
-const fakeInternalInstance: {
77
- _processChildContext?: () => empty,
78
-} = {};
76
+const fakeInternalInstance = {};
77
78
let didWarnAboutStateAssignmentForComponent;
79
let didWarnAboutUninitializedState;
@@ -98,24 +96,6 @@ if (__DEV__) {
96
didWarnAboutInvalidateContextType = new Set<string>();
97
didWarnOnInvalidCallback = new Set<string>();
98
101
- // This is so gross but it's at least non-critical and can be removed if
102
- // it causes problems. This is meant to give a nicer error message for
103
- // ReactDOM15.unstable_renderSubtreeIntoContainer(reactDOM16Component,
104
- // ...)) which otherwise throws a "_processChildContext is not a function"
105
- // exception.
106
- Object.defineProperty(fakeInternalInstance, '_processChildContext', {
107
- enumerable: false,
108
- value: function (): empty {
109
- throw new Error(
110
- '_processChildContext is not available in React 16+. This likely ' +
111
- 'means you have multiple copies of React and are attempting to nest ' +
112
- 'a React 15 tree inside a React 16 tree using ' +
113
- "unstable_renderSubtreeIntoContainer, which isn't supported. Try " +
114
- 'to make sure you have only one copy of React (and ideally, switch ' +
115
- 'to ReactDOM.createPortal).',
116
- );
117
- },
118
- });
99
Object.freeze(fakeInternalInstance);
100
}
101
packages/shared/ReactInstanceMap.js
-13
@@ -15,23 +15,10 @@
15
* If this becomes an actual Map, that will break.
16
*/
17
18
-/**
19
- * This API should be called `delete` but we'd have to make sure to always
20
- * transform these to strings for IE support. When this transform is fully
21
- * supported we can rename it.
22
- */
23
-export function remove(key) {
24
- key._reactInternals = undefined;
25
-}
26
-
18
export function get(key) {
19
return key._reactInternals;
20
}
21
31
-export function has(key) {
32
- return key._reactInternals !== undefined;
33
-}
34
-
22
export function set(key, value) {
23
key._reactInternals = value;
24
}