main
js 172 lines 4.54 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 describe('ReactStrictMode', () => {
13 let React;
14 let ReactDOMClient;
15 let act;
16
17 beforeEach(() => {
18 jest.resetModules();
19 React = require('react');
20 ReactDOMClient = require('react-dom/client');
21
22 act = require('internal-test-utils').act;
23 });
24
25 describe('levels', () => {
26 let log;
27
28 beforeEach(() => {
29 log = [];
30 });
31
32 function Component({label}) {
33 React.useEffect(() => {
34 log.push(`${label}: useEffect mount`);
35 return () => log.push(`${label}: useEffect unmount`);
36 });
37
38 React.useLayoutEffect(() => {
39 log.push(`${label}: useLayoutEffect mount`);
40 return () => log.push(`${label}: useLayoutEffect unmount`);
41 });
42
43 log.push(`${label}: render`);
44
45 return null;
46 }
47
48 it('should default to not strict', async () => {
49 await act(() => {
50 const container = document.createElement('div');
51 const root = ReactDOMClient.createRoot(container);
52 root.render(<Component label="A" />);
53 });
54
55 expect(log).toEqual([
56 'A: render',
57 'A: useLayoutEffect mount',
58 'A: useEffect mount',
59 ]);
60 });
61
62 if (__DEV__) {
63 it('should support enabling strict mode via createRoot option', async () => {
64 await act(() => {
65 const container = document.createElement('div');
66 const root = ReactDOMClient.createRoot(container, {
67 unstable_strictMode: true,
68 });
69 root.render(<Component label="A" />);
70 });
71
72 expect(log).toEqual([
73 'A: render',
74 'A: render',
75 'A: useLayoutEffect mount',
76 'A: useEffect mount',
77 'A: useLayoutEffect unmount',
78 'A: useEffect unmount',
79 'A: useLayoutEffect mount',
80 'A: useEffect mount',
81 ]);
82 });
83
84 it('should include legacy + strict effects mode', async () => {
85 await act(() => {
86 const container = document.createElement('div');
87 const root = ReactDOMClient.createRoot(container);
88 root.render(
89 <React.StrictMode>
90 <Component label="A" />
91 </React.StrictMode>,
92 );
93 });
94
95 expect(log).toEqual([
96 'A: render',
97 'A: render',
98 'A: useLayoutEffect mount',
99 'A: useEffect mount',
100 'A: useLayoutEffect unmount',
101 'A: useEffect unmount',
102 'A: useLayoutEffect mount',
103 'A: useEffect mount',
104 ]);
105 });
106
107 it('should allow level to be increased with nesting', async () => {
108 await act(() => {
109 const container = document.createElement('div');
110 const root = ReactDOMClient.createRoot(container);
111 root.render(
112 <>
113 <Component label="A" />
114 <React.StrictMode>
115 <Component label="B" />,
116 </React.StrictMode>
117 ,
118 </>,
119 );
120 });
121
122 expect(log).toEqual([
123 'A: render',
124 'B: render',
125 'B: render',
126 'A: useLayoutEffect mount',
127 'B: useLayoutEffect mount',
128 'A: useEffect mount',
129 'B: useEffect mount',
130 'B: useLayoutEffect unmount',
131 'B: useEffect unmount',
132 'B: useLayoutEffect mount',
133 'B: useEffect mount',
134 ]);
135 });
136
137 it('should support nested strict mode on initial mount', async () => {
138 function Wrapper({children}) {
139 return children;
140 }
141 await act(() => {
142 const container = document.createElement('div');
143 const root = ReactDOMClient.createRoot(container);
144 root.render(
145 <Wrapper>
146 <Component label="A" />
147 <React.StrictMode>
148 <Component label="B" />,
149 </React.StrictMode>
150 ,
151 </Wrapper>,
152 );
153 });
154
155 expect(log).toEqual([
156 'A: render',
157 'B: render',
158 'B: render',
159 'A: useLayoutEffect mount',
160 'B: useLayoutEffect mount',
161 'A: useEffect mount',
162 'B: useEffect mount',
163 // TODO: this is currently broken
164 // 'B: useLayoutEffect unmount',
165 // 'B: useEffect unmount',
166 // 'B: useLayoutEffect mount',
167 // 'B: useEffect mount',
168 ]);
169 });
170 }
171 });
172 });