Skip to content

Commit 63c3456

Browse files
committed
Add coverage for cases where we reset nestedUpdateCounter
These cases explicitly verify that we reset the counter in right places.
1 parent e4b50e8 commit 63c3456

File tree

1 file changed

+80
-0
lines changed

1 file changed

+80
-0
lines changed

packages/react-dom/src/__tests__/ReactUpdates-test.js

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1312,6 +1312,46 @@ describe('ReactUpdates', () => {
13121312
ReactDOM.render(<Foo />, container);
13131313
});
13141314

1315+
it('resets the update counter for unrelated updates', () => {
1316+
const container = document.createElement('div');
1317+
const ref = React.createRef();
1318+
1319+
class EventuallyTerminating extends React.Component {
1320+
state = {step: 0};
1321+
componentDidMount() {
1322+
this.setState({step: 1});
1323+
}
1324+
componentDidUpdate() {
1325+
if (this.state.step < limit) {
1326+
this.setState({step: this.state.step + 1});
1327+
}
1328+
}
1329+
render() {
1330+
return this.state.step;
1331+
}
1332+
}
1333+
1334+
let limit = 55;
1335+
expect(() => {
1336+
ReactDOM.render(<EventuallyTerminating ref={ref} />, container);
1337+
}).toThrow('Maximum');
1338+
1339+
// Verify that we don't go over the limit if these updates are unrelated.
1340+
limit -= 10;
1341+
ReactDOM.render(<EventuallyTerminating ref={ref} />, container);
1342+
expect(container.textContent).toBe(limit.toString());
1343+
ref.current.setState({step: 0});
1344+
expect(container.textContent).toBe(limit.toString());
1345+
ref.current.setState({step: 0});
1346+
expect(container.textContent).toBe(limit.toString());
1347+
1348+
limit += 10;
1349+
expect(() => {
1350+
ref.current.setState({step: 0});
1351+
}).toThrow('Maximum');
1352+
expect(ref.current).toBe(null);
1353+
});
1354+
13151355
it('does not fall into an infinite update loop', () => {
13161356
class NonTerminating extends React.Component {
13171357
state = {step: 0};
@@ -1337,6 +1377,46 @@ describe('ReactUpdates', () => {
13371377
}).toThrow('Maximum');
13381378
});
13391379

1380+
it('can recover after falling into an infinite update loop', () => {
1381+
class NonTerminating extends React.Component {
1382+
state = {step: 0};
1383+
componentDidMount() {
1384+
this.setState({step: 1});
1385+
}
1386+
componentDidUpdate() {
1387+
this.setState({step: 2});
1388+
}
1389+
render() {
1390+
return this.state.step;
1391+
}
1392+
}
1393+
1394+
class Terminating extends React.Component {
1395+
state = {step: 0};
1396+
componentDidMount() {
1397+
this.setState({step: 1});
1398+
}
1399+
render() {
1400+
return this.state.step;
1401+
}
1402+
}
1403+
1404+
const container = document.createElement('div');
1405+
expect(() => {
1406+
ReactDOM.render(<NonTerminating />, container);
1407+
}).toThrow('Maximum');
1408+
1409+
ReactDOM.render(<Terminating />, container);
1410+
expect(container.textContent).toBe('1');
1411+
1412+
expect(() => {
1413+
ReactDOM.render(<NonTerminating />, container);
1414+
}).toThrow('Maximum');
1415+
1416+
ReactDOM.render(<Terminating />, container);
1417+
expect(container.textContent).toBe('1');
1418+
});
1419+
13401420
it('does not fall into an infinite error loop', () => {
13411421
function BadRender() {
13421422
throw new Error('error');

0 commit comments

Comments
 (0)