main
js 101 lines 3.41 KB
Raw
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 ReactDOM = require('react-dom');
14 const ReactDOMClient = require('react-dom/client');
15 const act = require('internal-test-utils').act;
16 const assertConsoleErrorDev =
17 require('internal-test-utils').assertConsoleErrorDev;
18
19 describe('ReactMount', () => {
20 it('should destroy a react root upon request', async () => {
21 const mainContainerDiv = document.createElement('div');
22 document.body.appendChild(mainContainerDiv);
23
24 const instanceOne = <div className="firstReactDiv" />;
25 const firstRootDiv = document.createElement('div');
26 mainContainerDiv.appendChild(firstRootDiv);
27 const firstRoot = ReactDOMClient.createRoot(firstRootDiv);
28 await act(() => {
29 firstRoot.render(instanceOne);
30 });
31
32 const instanceTwo = <div className="secondReactDiv" />;
33 const secondRootDiv = document.createElement('div');
34 mainContainerDiv.appendChild(secondRootDiv);
35 const secondRoot = ReactDOMClient.createRoot(secondRootDiv);
36 await act(() => {
37 secondRoot.render(instanceTwo);
38 });
39
40 // Test that two react roots are rendered in isolation
41 expect(firstRootDiv.firstChild.className).toBe('firstReactDiv');
42 expect(secondRootDiv.firstChild.className).toBe('secondReactDiv');
43
44 // Test that after unmounting each, they are no longer in the document.
45 await act(() => {
46 firstRoot.unmount();
47 });
48 expect(firstRootDiv.firstChild).toBeNull();
49 await act(() => {
50 secondRoot.unmount();
51 });
52 });
53
54 // @gate !disableLegacyMode
55 it('should warn when unmounting a non-container root node', () => {
56 const mainContainerDiv = document.createElement('div');
57
58 const component = (
59 <div>
60 <div />
61 </div>
62 );
63 // Cannot be migrated to createRoot until we remove unmountComponentAtNode i.e. remove this test.
64 ReactDOM.render(component, mainContainerDiv);
65
66 // Test that unmounting at a root node gives a helpful warning
67 const rootDiv = mainContainerDiv.firstChild;
68 ReactDOM.unmountComponentAtNode(rootDiv);
69 assertConsoleErrorDev([
70 "unmountComponentAtNode(): The node you're attempting to " +
71 'unmount was rendered by React and is not a top-level container. You ' +
72 'may have accidentally passed in a React root node instead of its ' +
73 'container.',
74 ]);
75 });
76
77 // @gate !disableLegacyMode
78 it('should warn when unmounting a non-container, non-root node', () => {
79 const mainContainerDiv = document.createElement('div');
80
81 const component = (
82 <div>
83 <div>
84 <div />
85 </div>
86 </div>
87 );
88 // Cannot be migrated to createRoot until we remove unmountComponentAtNode i.e. remove this test.
89 ReactDOM.render(component, mainContainerDiv);
90
91 // Test that unmounting at a non-root node gives a different warning
92 const nonRootDiv = mainContainerDiv.firstChild.firstChild;
93 ReactDOM.unmountComponentAtNode(nonRootDiv);
94 assertConsoleErrorDev([
95 "unmountComponentAtNode(): The node you're attempting to " +
96 'unmount was rendered by React and is not a top-level container. ' +
97 'Instead, have the parent component update its state and rerender in ' +
98 'order to remove this component.',
99 ]);
100 });
101 });