-
Notifications
You must be signed in to change notification settings - Fork 108
Description
- I have updated Purchases SDK to the latest version
- I have read the Contribution Guidelines
- I have searched the Community
- I have read docs.revenuecat.com
- I have searched for existing Github issues
Describe the bug
When showing the paywall with the PurchasesUI.Paywall component on iOS after navigating to a react-navigation screen, the app can freeze if you need to delay the mounting of the paywall component. There are no errors thrown or warns.
From my tests it happens only in the first time you show the paywall, if you successfully show it once, then you can't repro in the same app open. It also seems to be easier to reproduce depending on your react-navigation structure, which can indicate a potential conflict between the revcat paywall and react-navigation.
1. Environment
- Platform: iOS
- SDK version: 9.2.0
- OS version: 18.6
- Xcode/Android Studio version: XCode 16.4
- React Native version: 0.79.5
- SDK installation (CocoaPods + version or manual):
- How widespread is the issue. Percentage of devices affected. 100% of tested iOS real devices
We verified this on real iOS devices but not in the simulator. Does not happen on Android devices.
Other relevant package versions:
"react": "19.0.0",
"react-native": "0.79.5",
"react-native-purchases": "^9.2.0",
"react-native-purchases-ui": "^9.2.0",
"react-native-reanimated": "^3.19.1",
"react-native-safe-area-context": "^5.6.0",
"react-native-screens": "^4.13.1",
"react-native-gesture-handler": "^2.28.0",
"@react-navigation/bottom-tabs": "^7.4.6",
"@react-navigation/native": "^7.1.17",
"@react-navigation/stack": "ˆ7.4.7",
2. Debug logs that reproduce the issue
There are no errors thrown or warns. The app will eventually crash if you background/foreground once it freezes but it's simply because it's unresponsive.
3. Steps to reproduce, with a description of expected vs. actual behavior
I created a gist with a minimal app where I am reproducing the problem:
https://gist.github.com/leonardorib/b21a00b1d9e8b760f5c125e73cd68f5d
To repro, try to navigate to the paywall quickly. Just open the app and press the buttons to get there as shown in the video.
The issue is not guaranteed to happen. But in at most 3 tries I can get one.
If you don't get the issue, completely quit the app and reopen to try a new one.
This is how the freeze/crash looks like:
paywall-freeze-repro.MOV
This is the expected behavior:
paywall-freeze-expected.MOV
- Other information (e.g. stacktraces, related issues, suggestions how to fix, links for us to have context, eg. stackoverflow, etc.)
Key aspects:
- The navigation structure might contribute (navigators hierachy). When I tried to reproduce in a simpler navigation structure with a single stack navigator with some screens, it was harder to make it freeze, which is why I recreated something closer to our real app.
- Although react-navigation might be involved. If i replace
<PurchasesUI.Paywall />with something like<View><Text>Hello world</Text></View>, the issue doesn't happen. It only happened when the component being mounted was the paywall, which is the reason I am reporting it here. - It seems to happen when you delay the mounting of the paywall after navigating to the screen (e.g when loading something before showing the paywall). It feels like it is when the mounting happens right in the middle of the navigation animation
There is a workaround that makes it consistently work for me, which is replacing:
useEffect(() => {
// Simulates a loading state before showing the paywall
setTimeout(() => {
setCanShow(true);
}, CAN_SHOW_DELAY_MS);
}, []);with:
import { InteractionManager } from 'react-native';
//...
useEffect(() => {
// Simulates a loading state before showing the paywall
setTimeout(() => {
InteractionManager.runAfterInteractions(() => {
setCanShow(true);
})
}, CAN_SHOW_DELAY_MS);
}, []);This ensures animations and interactions are executed first. More info: https://reactnative.dev/docs/interactionmanager
To this moment, I didn't get the issue when ensuring I wait for runAfterInteractions, but since I don't know exactly what is behind the problem, I can't guarantee the safety of it.
Additional context
It could be that this ends up being an issue on react-navigation or even react-native-screens, but since I can only repro when trying to render the Paywall component specifically, I am reporting it here.
Let me know if you guys can reproduce it on your end with my gist.