Skip to content

Commit

Permalink
Add a pair of tests for removing the parent
Browse files Browse the repository at this point in the history
  • Loading branch information
gaearon committed Apr 5, 2022
1 parent 8ce0a24 commit 3ae6285
Showing 1 changed file with 118 additions and 2 deletions.
120 changes: 118 additions & 2 deletions packages/react-reconciler/src/__tests__/ReactLazy-test.internal.js
Expand Up @@ -1632,7 +1632,7 @@ describe('ReactLazy', () => {
expect(root).toMatchRenderedOutput('ba');
});

it('does not destroy layout effects twice', async () => {
it('does not destroy layout effects twice when hidden child is removed', async () => {
function ChildA({label}) {
React.useLayoutEffect(() => {
Scheduler.unstable_yieldValue('Did mount: ' + label);
Expand Down Expand Up @@ -1686,7 +1686,7 @@ describe('ReactLazy', () => {
expect(root).toMatchRenderedOutput('B');
});

it('does not call componentWillUnmount twice', async () => {
it('does not call componentWillUnmount twice when hidden child is removed', async () => {
class ChildA extends React.Component {
componentDidMount() {
Scheduler.unstable_yieldValue('Did mount: ' + this.props.label);
Expand Down Expand Up @@ -1743,4 +1743,120 @@ describe('ReactLazy', () => {
expect(Scheduler).toFlushAndYield(['B', 'Did mount: B']);
expect(root).toMatchRenderedOutput('B');
});

it('does not destroy layout effects twice when parent suspense is removed', async () => {
function ChildA({label}) {
React.useLayoutEffect(() => {
Scheduler.unstable_yieldValue('Did mount: ' + label);
return () => {
Scheduler.unstable_yieldValue('Will unmount: ' + label);
};
}, []);
return <Text text={label} />;
}
function ChildB({label}) {
React.useLayoutEffect(() => {
Scheduler.unstable_yieldValue('Did mount: ' + label);
return () => {
Scheduler.unstable_yieldValue('Will unmount: ' + label);
};
}, []);
return <Text text={label} />;
}
const LazyChildA = lazy(() => fakeImport(ChildA));
const LazyChildB = lazy(() => fakeImport(ChildB));

function Parent({swap}) {
return (
<Suspense fallback={<Text text="Loading..." />}>
{swap ? <LazyChildB label="B" /> : <LazyChildA label="A" />}
</Suspense>
);
}

const root = ReactTestRenderer.create(<Parent swap={false} />, {
unstable_isConcurrent: true,
});

expect(Scheduler).toFlushAndYield(['Loading...']);

await LazyChildA;
expect(Scheduler).toFlushAndYield(['A', 'Did mount: A']);
expect(root).toMatchRenderedOutput('A');

// Swap the position of A and B
root.unstable_flushSync(() => {
root.update(<Parent swap={true} />);
});
expect(Scheduler).toHaveYielded(['Loading...', 'Will unmount: A']);
expect(root).toMatchRenderedOutput('Loading...');

// Destroy the whole tree, including the hidden A
root.unstable_flushSync(() => {
root.update(<h1>Hello</h1>);
});
expect(Scheduler).toFlushAndYield([]);
expect(root).toMatchRenderedOutput(<h1>Hello</h1>);
});

it('does not call componentWillUnmount twice when parent suspense is removed', async () => {
class ChildA extends React.Component {
componentDidMount() {
Scheduler.unstable_yieldValue('Did mount: ' + this.props.label);
}
componentWillUnmount() {
Scheduler.unstable_yieldValue('Will unmount: ' + this.props.label);
}
render() {
return <Text text={this.props.label} />;
}
}

class ChildB extends React.Component {
componentDidMount() {
Scheduler.unstable_yieldValue('Did mount: ' + this.props.label);
}
componentWillUnmount() {
Scheduler.unstable_yieldValue('Will unmount: ' + this.props.label);
}
render() {
return <Text text={this.props.label} />;
}
}

const LazyChildA = lazy(() => fakeImport(ChildA));
const LazyChildB = lazy(() => fakeImport(ChildB));

function Parent({swap}) {
return (
<Suspense fallback={<Text text="Loading..." />}>
{swap ? <LazyChildB label="B" /> : <LazyChildA label="A" />}
</Suspense>
);
}

const root = ReactTestRenderer.create(<Parent swap={false} />, {
unstable_isConcurrent: true,
});

expect(Scheduler).toFlushAndYield(['Loading...']);

await LazyChildA;
expect(Scheduler).toFlushAndYield(['A', 'Did mount: A']);
expect(root).toMatchRenderedOutput('A');

// Swap the position of A and B
root.unstable_flushSync(() => {
root.update(<Parent swap={true} />);
});
expect(Scheduler).toHaveYielded(['Loading...', 'Will unmount: A']);
expect(root).toMatchRenderedOutput('Loading...');

// Destroy the whole tree, including the hidden A
root.unstable_flushSync(() => {
root.update(<h1>Hello</h1>);
});
expect(Scheduler).toFlushAndYield([]);
expect(root).toMatchRenderedOutput(<h1>Hello</h1>);
});
});

0 comments on commit 3ae6285

Please sign in to comment.