Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert ReactComponentLifeycle to createRoot #28178

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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