@@ -1316,14 +1341,18 @@ describe('ReactUpdates', () => {
);
}
- // Mount
- ReactDOM.render(
, container);
- expect(ops).toEqual(['Foo', 'Bar', 'Baz']);
- ops = [];
+ const root = ReactDOMClient.createRoot(container);
+ await act(() => {
+ // Mount
+ root.render(
);
+ });
+ assertLog(['Foo', 'Bar', 'Baz']);
- // Update
- ReactDOM.render(
, container);
- expect(ops).toEqual(['Foo', 'Bar', 'Baz']);
+ await act(() => {
+ // Update
+ root.render(
);
+ });
+ assertLog(['Foo', 'Bar', 'Baz']);
});
// @gate www
@@ -1383,18 +1412,33 @@ describe('ReactUpdates', () => {
expect(hiddenDiv.innerHTML).toBe('
bar 1
');
});
- it('can render ridiculously large number of roots without triggering infinite update loop error', () => {
+ it('can render ridiculously large number of roots without triggering infinite update loop error', async () => {
+ function Component({trigger}) {
+ const [state, setState] = React.useState(0);
+
+ React.useEffect(() => {
+ if (trigger) {
+ Scheduler.log('Trigger');
+ setState(c => c + 1);
+ }
+ }, [trigger]);
+
+ return
{state}
;
+ }
+
class Foo extends React.Component {
componentDidMount() {
const limit = 1200;
for (let i = 0; i < limit; i++) {
if (i < limit - 1) {
- ReactDOM.render(
, document.createElement('div'));
+ ReactDOMClient.createRoot(document.createElement('div')).render(
+
,
+ );
} else {
- ReactDOM.render(
, document.createElement('div'), () => {
- // The "nested update limit" error isn't thrown until setState
- this.setState({});
- });
+ // The "nested update limit" error isn't thrown until setState
+ ReactDOMClient.createRoot(document.createElement('div')).render(
+
,
+ );
}
}
}
@@ -1403,11 +1447,16 @@ describe('ReactUpdates', () => {
}
}
- const container = document.createElement('div');
- ReactDOM.render(
, container);
+ const root = ReactDOMClient.createRoot(document.createElement('div'));
+ await act(() => {
+ root.render(
);
+ });
+
+ // Make sure the setState trigger runs.
+ assertLog(['Trigger']);
});
- it('resets the update counter for unrelated updates', () => {
+ it('resets the update counter for unrelated updates', async () => {
const container = document.createElement('div');
const ref = React.createRef();
@@ -1427,22 +1476,35 @@ describe('ReactUpdates', () => {
}
let limit = 55;
+ const root = ReactDOMClient.createRoot(container);
expect(() => {
- ReactDOM.render(
, container);
+ ReactDOM.flushSync(() => {
+ root.render(
);
+ });
}).toThrow('Maximum');
// Verify that we don't go over the limit if these updates are unrelated.
limit -= 10;
- ReactDOM.render(
, container);
+ await act(() => {
+ root.render(
);
+ });
expect(container.textContent).toBe(limit.toString());
- ref.current.setState({step: 0});
+
+ await act(() => {
+ ref.current.setState({step: 0});
+ });
expect(container.textContent).toBe(limit.toString());
- ref.current.setState({step: 0});
+
+ await act(() => {
+ ref.current.setState({step: 0});
+ });
expect(container.textContent).toBe(limit.toString());
limit += 10;
expect(() => {
- ref.current.setState({step: 0});
+ ReactDOM.flushSync(() => {
+ ref.current.setState({step: 0});
+ });
}).toThrow('Maximum');
expect(ref.current).toBe(null);
});
@@ -1450,12 +1512,15 @@ describe('ReactUpdates', () => {
it('does not fall into an infinite update loop', () => {
class NonTerminating extends React.Component {
state = {step: 0};
+
componentDidMount() {
this.setState({step: 1});
}
- UNSAFE_componentWillUpdate() {
+
+ componentDidUpdate() {
this.setState({step: 2});
}
+
render() {
return (
@@ -1467,8 +1532,12 @@ describe('ReactUpdates', () => {
}
const container = document.createElement('div');
+ const root = ReactDOMClient.createRoot(container);
+
expect(() => {
- ReactDOM.render(
, container);
+ ReactDOM.flushSync(() => {
+ root.render(
);
+ });
}).toThrow('Maximum');
});
@@ -1482,12 +1551,15 @@ describe('ReactUpdates', () => {
}
const container = document.createElement('div');
+ const root = ReactDOMClient.createRoot(container);
expect(() => {
- ReactDOM.render(
, container);
+ ReactDOM.flushSync(() => {
+ root.render(
);
+ });
}).toThrow('Maximum');
});
- it('can recover after falling into an infinite update loop', () => {
+ it('can recover after falling into an infinite update loop', async () => {
class NonTerminating extends React.Component {
state = {step: 0};
componentDidMount() {
@@ -1512,27 +1584,36 @@ describe('ReactUpdates', () => {
}
const container = document.createElement('div');
+ const root = ReactDOMClient.createRoot(container);
expect(() => {
- ReactDOM.render(
, container);
+ ReactDOM.flushSync(() => {
+ root.render(
);
+ });
}).toThrow('Maximum');
- ReactDOM.render(
, container);
+ await act(() => {
+ root.render(
);
+ });
expect(container.textContent).toBe('1');
expect(() => {
- ReactDOM.render(
, container);
+ ReactDOM.flushSync(() => {
+ root.render(
);
+ });
}).toThrow('Maximum');
-
- ReactDOM.render(
, container);
+ await act(() => {
+ root.render(
);
+ });
expect(container.textContent).toBe('1');
});
it('does not fall into mutually recursive infinite update loop with same container', () => {
// Note: this test would fail if there were two or more different roots.
-
+ const container = document.createElement('div');
+ const root = ReactDOMClient.createRoot(container);
class A extends React.Component {
componentDidMount() {
- ReactDOM.render(
, container);
+ root.render(
);
}
render() {
return null;
@@ -1541,16 +1622,17 @@ describe('ReactUpdates', () => {
class B extends React.Component {
componentDidMount() {
- ReactDOM.render(
, container);
+ root.render(
);
}
render() {
return null;
}
}
- const container = document.createElement('div');
expect(() => {
- ReactDOM.render(
, container);
+ ReactDOM.flushSync(() => {
+ root.render(
);
+ });
}).toThrow('Maximum');
});
@@ -1582,14 +1664,17 @@ describe('ReactUpdates', () => {
}
const container = document.createElement('div');
+ const root = ReactDOMClient.createRoot(container);
expect(() => {
- ReactDOM.render(
, container);
+ ReactDOM.flushSync(() => {
+ root.render(
);
+ });
}).toThrow('Maximum');
});
- it('can schedule ridiculously many updates within the same batch without triggering a maximum update error', () => {
+ it('can schedule ridiculously many updates within the same batch without triggering a maximum update error', async () => {
const subscribers = [];
-
+ const limit = 1200;
class Child extends React.Component {
state = {value: 'initial'};
componentDidMount() {
@@ -1603,7 +1688,7 @@ describe('ReactUpdates', () => {
class App extends React.Component {
render() {
const children = [];
- for (let i = 0; i < 1200; i++) {
+ for (let i = 0; i < limit; i++) {
children.push(
);
}
return children;
@@ -1611,13 +1696,18 @@ describe('ReactUpdates', () => {
}
const container = document.createElement('div');
- ReactDOM.render(
, container);
+ const root = ReactDOMClient.createRoot(container);
+ await act(() => {
+ root.render(
);
+ });
- ReactDOM.unstable_batchedUpdates(() => {
+ await act(() => {
subscribers.forEach(s => {
s.setState({value: 'update'});
});
});
+
+ expect(subscribers.length).toBe(limit);
});
// TODO: Replace this branch with @gate pragmas
@@ -1673,8 +1763,9 @@ describe('ReactUpdates', () => {
}
const container = document.createElement('div');
+ const root = ReactDOMClient.createRoot(container);
await act(() => {
- ReactDOM.render(
, container);
+ root.render(
);
});
expect(container.textContent).toBe('50');
await act(() => {
@@ -1696,8 +1787,9 @@ describe('ReactUpdates', () => {
}
const container = document.createElement('div');
+ const root = ReactDOMClient.createRoot(container);
await act(() => {
- ReactDOM.render(
, container);
+ root.render(
);
});
assertLog(['Done']);