Portal stays visible indefinitely if unmounted immediately after mounting
See original GitHub issueCurrent behaviour
When trying to remove a portal immediately after mounting it, it stays visible indefinitely. See the failing test below.
Expected behaviour
The portal is unmounted and does not stay visible.
Code sample
Here’s a minimal failing test case (something equivalent happened to me in more complicated, real world code)
import React, { useEffect, useState } from 'react';
import { Portal, Text } from 'react-native-paper';
import { render, waitForElement } from 'react-native-testing-library';
const TestComponent = () => {
const [isPortalVisible, setIsPortalVisible] = useState(true);
useEffect(() => {
// Unmount the portal immediately after mounting it
setIsPortalVisible(false);
}, []);
return (
<Portal.Host>
{isPortalVisible && (
<Portal>
<Text>{"I'm here"}</Text>
</Portal>
)}
</Portal.Host>
);
};
test('portal is properly unmounted', async () => {
const component = render(<TestComponent />);
// This expectation is failing, the portal is never unmounted, despite the useEffect
await waitForElement(() => {
const portalContent = component.queryByText("I'm here");
if (portalContent) throw new Error('Portal is still visible');
});
});
What have you tried
The cause seems to be with the await
here:
https://github.com/callstack/react-native-paper/blob/975cfa3be4956b629aa8255e226ff9ca068448eb/src/components/Portal/PortalConsumer.tsx#L10-L17
The await in componentDidMount
causes a race condition with the synchronous unmounting:
https://github.com/callstack/react-native-paper/blob/975cfa3be4956b629aa8255e226ff9ca068448eb/src/components/Portal/PortalConsumer.tsx#L25-L29
The portal gets (not really) unmounted before being mounted → it stays registered with the portal manager.
One possible fix is to make componentWillUnmount async too:
- componentWillUnmount() {
+ async componentWillUnmount() {
this._checkManager();
+ await Promise.resolve();
this.props.manager.unmount(this._key);
}
I’m not sure why the await Promise.resolve()
was introduced, so I can’t tell for sure if it’s possible to fix this in a cleaner way.
Your Environment
software | version |
---|---|
ios or android | irrelevant |
react-native | 0.63.3 |
react-native-paper | bug confirmed in 2.16 and 4.7.2 |
node | 14.15 |
npm or yarn | irrelevant |
expo sdk | not used |
Issue Analytics
- State:
- Created 3 years ago
- Reactions:5
- Comments:11
Top GitHub Comments
Still an issue
use https://www.npmjs.com/package/patch-package