Skip to content

Commit

Permalink
Convert ReactComponentLifeycle to createRoot (#28178)
Browse files Browse the repository at this point in the history
  • Loading branch information
eps1lon committed Feb 2, 2024
1 parent 11aa263 commit e9c13cd
Showing 1 changed file with 69 additions and 26 deletions.
95 changes: 69 additions & 26 deletions packages/react-dom/src/__tests__/ReactComponentLifeCycle-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,17 +113,29 @@ describe('ReactComponentLifeCycle', () => {
}

const element = <StatefulComponent />;
const firstInstance = ReactDOM.render(element, container);
ReactDOM.unmountComponentAtNode(container);
const secondInstance = ReactDOM.render(element, container);
let root = ReactDOMClient.createRoot(container);
await act(() => {
root.render(element);
});

const firstInstance = container.firstChild;
await act(() => {
root.unmount();
});
root = ReactDOMClient.createRoot(container);
await act(() => {
root.render(element);
});

const secondInstance = container.firstChild;
expect(firstInstance).not.toBe(secondInstance);
});

/**
* If a state update triggers rerendering that in turn fires an onDOMReady,
* that second onDOMReady should not fail.
*/
it('it should fire onDOMReady when already in onDOMReady', () => {
it('it should fire onDOMReady when already in onDOMReady', async () => {
const _testJournal = [];

class Child extends React.Component {
Expand Down Expand Up @@ -161,7 +173,13 @@ describe('ReactComponentLifeCycle', () => {
}
}

ReactTestUtils.renderIntoDocument(<SwitcherParent />);
const container = document.createElement('div');
const root = ReactDOMClient.createRoot(container);

await act(() => {
root.render(<SwitcherParent />);
});

expect(_testJournal).toEqual([
'SwitcherParent:getInitialState',
'SwitcherParent:onDOMReady',
Expand Down Expand Up @@ -205,7 +223,7 @@ describe('ReactComponentLifeCycle', () => {
}).not.toThrow();
});

it("warns if setting 'this.state = props'", () => {
it("warns if setting 'this.state = props'", async () => {
class StatefulComponent extends React.Component {
constructor(props, context) {
super(props, context);
Expand All @@ -216,16 +234,20 @@ describe('ReactComponentLifeCycle', () => {
}
}

expect(() => {
ReactTestUtils.renderIntoDocument(<StatefulComponent />);
const container = document.createElement('div');
const root = ReactDOMClient.createRoot(container);
await expect(async () => {
await act(() => {
root.render(<StatefulComponent />);
});
}).toErrorDev(
'StatefulComponent: It is not recommended to assign props directly to state ' +
"because updates to props won't be reflected in state. " +
'In most cases, it is better to use props directly.',
);
});

it('should not allow update state inside of getInitialState', () => {
it('should not allow update state inside of getInitialState', async () => {
class StatefulComponent extends React.Component {
constructor(props, context) {
super(props, context);
Expand All @@ -239,20 +261,27 @@ describe('ReactComponentLifeCycle', () => {
}
}

expect(() => {
ReactTestUtils.renderIntoDocument(<StatefulComponent />);
let container = document.createElement('div');
let root = ReactDOMClient.createRoot(container);
await expect(async () => {
await act(() => {
root.render(<StatefulComponent />);
});
}).toErrorDev(
"Warning: Can't call setState on a component that is not yet mounted. " +
'This is a no-op, but it might indicate a bug in your application. ' +
'Instead, assign to `this.state` directly or define a `state = {};` ' +
'class property with the desired state in the StatefulComponent component.',
);

// Check deduplication; (no extra warnings should be logged).
ReactTestUtils.renderIntoDocument(<StatefulComponent />);
container = document.createElement('div');
root = ReactDOMClient.createRoot(container);
await act(() => {
root.render(<StatefulComponent />);
});
});

it('should correctly determine if a component is mounted', () => {
it('should correctly determine if a component is mounted', async () => {
class Component extends React.Component {
_isMounted() {
// No longer a public API, but we can test that it works internally by
Expand All @@ -271,15 +300,20 @@ describe('ReactComponentLifeCycle', () => {
}
}

const element = <Component />;
let instance;
const element = <Component ref={current => (instance = current)} />;

expect(() => {
const instance = ReactTestUtils.renderIntoDocument(element);
expect(instance._isMounted()).toBeTruthy();
const container = document.createElement('div');
const root = ReactDOMClient.createRoot(container);
await expect(async () => {
await act(() => {
root.render(element);
});
}).toErrorDev('Component is accessing isMounted inside its render()');
expect(instance._isMounted()).toBeTruthy();
});

it('should correctly determine if a null component is mounted', () => {
it('should correctly determine if a null component is mounted', async () => {
class Component extends React.Component {
_isMounted() {
// No longer a public API, but we can test that it works internally by
Expand All @@ -298,12 +332,17 @@ describe('ReactComponentLifeCycle', () => {
}
}

const element = <Component />;
let instance;
const element = <Component ref={current => (instance = current)} />;

expect(() => {
const instance = ReactTestUtils.renderIntoDocument(element);
expect(instance._isMounted()).toBeTruthy();
const container = document.createElement('div');
const root = ReactDOMClient.createRoot(container);
await expect(async () => {
await act(() => {
root.render(element);
});
}).toErrorDev('Component is accessing isMounted inside its render()');
expect(instance._isMounted()).toBeTruthy();
});

it('isMounted should return false when unmounted', async () => {
Expand Down Expand Up @@ -331,7 +370,7 @@ describe('ReactComponentLifeCycle', () => {
expect(instance.updater.isMounted(instance)).toBe(false);
});

it('warns if findDOMNode is used inside render', () => {
it('warns if legacy findDOMNode is used inside render', async () => {
class Component extends React.Component {
state = {isMounted: false};
componentDidMount() {
Expand All @@ -345,8 +384,12 @@ describe('ReactComponentLifeCycle', () => {
}
}

expect(() => {
ReactTestUtils.renderIntoDocument(<Component />);
const container = document.createElement('div');
const root = ReactDOMClient.createRoot(container);
await expect(async () => {
await act(() => {
root.render(<Component />);
});
}).toErrorDev('Component is accessing findDOMNode inside its render()');
});

Expand Down

0 comments on commit e9c13cd

Please sign in to comment.