Convert refs-destruction to createRoot (#28011)
Ricky committed
Jan 24, 2024 at 14:22 UTC
72411c45f94565c30215b51cbadb16fcc3479d37
1 file changed
+69
-38
packages/react-dom/src/__tests__/refs-destruction-test.js
+69
-38
@@ -11,9 +11,12 @@
11
12
let React;
13
let ReactDOM;
14
+let ReactDOMClient;
15
let ReactTestUtils;
15
-
16
let TestComponent;
17
+let act;
18
+let theInnerDivRef;
19
+let theInnerClassComponentRef;
20
21
describe('refs-destruction', () => {
22
beforeEach(() => {
@@ -21,7 +24,9 @@ describe('refs-destruction', () => {
24
25
React = require('react');
26
ReactDOM = require('react-dom');
27
+ ReactDOMClient = require('react-dom/client');
28
ReactTestUtils = require('react-dom/test-utils');
29
+ act = require('internal-test-utils').act;
30
31
class ClassComponent extends React.Component {
32
render() {
@@ -30,8 +35,11 @@ describe('refs-destruction', () => {
35
}
36
37
TestComponent = class extends React.Component {
33
- theInnerDivRef = React.createRef();
34
- theInnerClassComponentRef = React.createRef();
38
+ constructor(props) {
39
+ super(props);
40
+ theInnerDivRef = React.createRef();
41
+ theInnerClassComponentRef = React.createRef();
42
+ }
43
44
render() {
45
if (this.props.destroy) {
@@ -46,8 +54,8 @@ describe('refs-destruction', () => {
54
} else {
55
return (
56
<div>
49
- <div ref={this.theInnerDivRef} />
50
- <ClassComponent ref={this.theInnerClassComponentRef} />
57
+ <div ref={theInnerDivRef} />
58
+ <ClassComponent ref={theInnerClassComponentRef} />
59
</div>
60
);
61
}
@@ -55,60 +63,79 @@ describe('refs-destruction', () => {
63
};
64
});
65
58
- it('should remove refs when destroying the parent', () => {
66
+ afterEach(() => {
67
+ theInnerClassComponentRef = null;
68
+ theInnerDivRef = null;
69
+ });
70
+
71
+ it('should remove refs when destroying the parent', async () => {
72
const container = document.createElement('div');
60
- const testInstance = ReactDOM.render(<TestComponent />, container);
73
+ const root = ReactDOMClient.createRoot(container);
74
+ await act(async () => {
75
+ root.render(<TestComponent />);
76
+ });
77
62
- expect(
63
- ReactTestUtils.isDOMComponent(testInstance.theInnerDivRef.current),
64
- ).toBe(true);
65
- expect(testInstance.theInnerClassComponentRef.current).toBeTruthy();
78
+ expect(ReactTestUtils.isDOMComponent(theInnerDivRef.current)).toBe(true);
79
+ expect(theInnerClassComponentRef.current).toBeTruthy();
80
67
- ReactDOM.unmountComponentAtNode(container);
81
+ root.unmount();
82
69
- expect(testInstance.theInnerDivRef.current).toBe(null);
70
- expect(testInstance.theInnerClassComponentRef.current).toBe(null);
83
+ expect(theInnerDivRef.current).toBe(null);
84
+ expect(theInnerClassComponentRef.current).toBe(null);
85
});
86
73
- it('should remove refs when destroying the child', () => {
87
+ it('should remove refs when destroying the child', async () => {
88
const container = document.createElement('div');
75
- const testInstance = ReactDOM.render(<TestComponent />, container);
76
- expect(
77
- ReactTestUtils.isDOMComponent(testInstance.theInnerDivRef.current),
78
- ).toBe(true);
79
- expect(testInstance.theInnerClassComponentRef.current).toBeTruthy();
89
+ const root = ReactDOMClient.createRoot(container);
90
+ await act(async () => {
91
+ root.render(<TestComponent />);
92
+ });
93
+
94
+ expect(ReactTestUtils.isDOMComponent(theInnerDivRef.current)).toBe(true);
95
+ expect(theInnerClassComponentRef.current).toBeTruthy();
96
81
- ReactDOM.render(<TestComponent destroy={true} />, container);
97
+ await act(async () => {
98
+ root.render(<TestComponent destroy={true} />);
99
+ });
100
83
- expect(testInstance.theInnerDivRef.current).toBe(null);
84
- expect(testInstance.theInnerClassComponentRef.current).toBe(null);
101
+ expect(theInnerDivRef.current).toBe(null);
102
+ expect(theInnerClassComponentRef.current).toBe(null);
103
});
104
87
- it('should remove refs when removing the child ref attribute', () => {
105
+ it('should remove refs when removing the child ref attribute', async () => {
106
const container = document.createElement('div');
89
- const testInstance = ReactDOM.render(<TestComponent />, container);
107
+ const root = ReactDOMClient.createRoot(container);
108
+ await act(async () => {
109
+ root.render(<TestComponent />);
110
+ });
111
91
- expect(
92
- ReactTestUtils.isDOMComponent(testInstance.theInnerDivRef.current),
93
- ).toBe(true);
94
- expect(testInstance.theInnerClassComponentRef.current).toBeTruthy();
112
+ expect(ReactTestUtils.isDOMComponent(theInnerDivRef.current)).toBe(true);
113
+ expect(theInnerClassComponentRef.current).toBeTruthy();
114
96
- ReactDOM.render(<TestComponent removeRef={true} />, container);
115
+ await act(async () => {
116
+ root.render(<TestComponent removeRef={true} />);
117
+ });
118
98
- expect(testInstance.theInnerDivRef.current).toBe(null);
99
- expect(testInstance.theInnerClassComponentRef.current).toBe(null);
119
+ expect(theInnerDivRef.current).toBe(null);
120
+ expect(theInnerClassComponentRef.current).toBe(null);
121
});
122
102
- it('should not error when destroying child with ref asynchronously', () => {
123
+ it('should not error when destroying child with ref asynchronously', async () => {
124
+ let nestedRoot;
125
class Modal extends React.Component {
126
componentDidMount() {
127
this.div = document.createElement('div');
128
+ nestedRoot = ReactDOMClient.createRoot(this.div);
129
document.body.appendChild(this.div);
130
this.componentDidUpdate();
131
}
132
133
componentDidUpdate() {
111
- ReactDOM.render(<div>{this.props.children}</div>, this.div);
134
+ setTimeout(() => {
135
+ ReactDOM.flushSync(() => {
136
+ nestedRoot.render(<div>{this.props.children}</div>);
137
+ });
138
+ }, 0);
139
}
140
141
componentWillUnmount() {
@@ -116,7 +143,7 @@ describe('refs-destruction', () => {
143
// some async animation
144
setTimeout(function () {
145
expect(function () {
119
- ReactDOM.unmountComponentAtNode(self.div);
146
+ nestedRoot.unmount();
147
}).not.toThrow();
148
document.body.removeChild(self.div);
149
}, 0);
@@ -144,8 +171,12 @@ describe('refs-destruction', () => {
171
}
172
173
const container = document.createElement('div');
147
- ReactDOM.render(<App />, container);
148
- ReactDOM.render(<App hidden={true} />, container);
149
- jest.runAllTimers();
174
+ const root = ReactDOMClient.createRoot(container);
175
+ await act(async () => {
176
+ root.render(<App />);
177
+ });
178
+ await act(async () => {
179
+ root.render(<App hidden={true} />);
180
+ });
181
});
182
});