Modal's children are rendered in the top left corner for the first few frames when it's opened (Android)
Description
When opening the Modal by settings its visibility to true the modal's children are rendered in the top left corner for the first few frames before the children snap to the correct position.
The issue appeared after upgrading our project to the newest version of react-native with newArch enabled. The issue was not present when testing the same project under the older version from which we were updating which was react-native: 0.73.3.
Steps to reproduce
- Open the provided expo snack
- Select "Android" (the issue is not visible in the web version)
- Click the "SHOW MODAL" button
- The red box with the text is rendered in the top left corner for the first few frames, after that it is rerendered in the correct position (the center of the screen)
Since Expo Snack tends to be a bit laggy and shown to the user at a lower FPS on Android, the issue might not be immediately noticeable—it could take a few tries to see the problem properly. I've also included a video from my physical device where the issue is clearly visible.
React Native Version
0.78.2
Affected Platforms
Runtime - Android
Output of npx @react-native-community/cli info
System:
OS: Linux 6.11 Fedora Linux 39 (Workstation Edition)
CPU: (12) x64 AMD Ryzen 5 7535U with Radeon Graphics
Memory: 4.17 GB / 13.33 GB
Shell:
version: 5.2.26
path: /bin/bash
Binaries:
Node:
version: 22.14.0
path: ~/.nvm/versions/node/v22.14.0/bin/node
Yarn:
version: 1.22.22
path: /usr/bin/yarn
npm:
version: 10.9.2
path: ~/.nvm/versions/node/v22.14.0/bin/npm
Watchman:
version: 20231008.002904.0
path: /usr/local/bin/watchman
SDKs:
Android SDK: Not Found
IDEs:
Android Studio: Not Found
Languages:
Java:
version: 17.0.9
path: /home/pavelroj/.sdkman/candidates/java/current/bin/javac
Ruby: Not Found
npmPackages:
"@react-native-community/cli":
installed: 15.0.1
wanted: 15.0.1
react:
installed: 19.0.0
wanted: 19.0.0
react-native:
installed: 0.78.2
wanted: 0.78.2
npmGlobalPackages:
"*react-native*": Not Found
Android:
hermesEnabled: true
newArchEnabled: true
iOS:
hermesEnabled: Not found
newArchEnabled: false
Stacktrace or Logs
No logs are needed since the issue doesn't cause a crash.
Reproducer
https://snack.expo.dev/@pavelroj/rn-modal-flicker-bug?platform=android
Screenshots and Videos
The issue reproduced on a physical device
https://github.com/user-attachments/assets/75e2255e-ac1f-4264-93a5-1d48398e8bee
[!TIP] Newer version available: You are on a supported minor version, but it looks like there's a newer patch available - 0.78.2. Please upgrade to the highest patch for your minor or latest and verify if the issue persists (alternatively, create a new project and repro the issue in it). If it does not repro, please let us know so we can close out this issue. This helps us ensure we are looking at issues that still exist in the most recent releases.
[!TIP] Newer version available: You are on a supported minor version, but it looks like there's a newer patch available - undefined. Please upgrade to the highest patch for your minor or latest and verify if the issue persists (alternatively, create a new project and repro the issue in it). If it does not repro, please let us know so we can close out this issue. This helps us ensure we are looking at issues that still exist in the most recent releases.
Updated to 0.78.2 - the issue still persists
Hi @pavel-roj I cannot see modal in snack you have shared, if you have missed adding it by mistake can u please update it and share the link again so that issue can be validated quickly
@devanshsaini11 My bad, it seems I didn't save it properly. Can you try now? (the link - https://snack.expo.dev/@pavelroj/rn-modal-flicker-bug?platform=android - is same)
Same problem here. Using "react-native": "0.76.7". Any idea on how to fix this?
Same problem here. Using "react-native": "0.77.0". Any idea on how to fix this?
Same problem here. Using "react-native": "0.77.0". Any idea on how to fix this?
You can fix this by set width、height of child view
const {width: screenWidth, height: screenHeight} = Dimensions.get('window')
<Modal
transparent
statusBarTranslucent
navigationBarTranslucent
hardwareAccelerated
animationType="fade"
onRequestClose={() => {}}>
<View
style={{
width: screenWidth,
height: screenHeight,
...
Same problem here. Using "react-native": "0.77.0". Any idea on how to fix this?
You can fix this by set width、height of child view
const {width: screenWidth, height: screenHeight} = Dimensions.get('window') <Modal transparent statusBarTranslucent navigationBarTranslucent hardwareAccelerated animationType="fade" onRequestClose={() => {}}> <View style={{ width: screenWidth, height: screenHeight, ...
It works good with animationType={"fade"}, your fix. Without it sometimes it has a small flash of items badly placed in the upper part of screen. on "react-native": "0.76.7". at least.
I added a PR which has a consistent reproducible using the rn-tester plus a few remarks: https://github.com/facebook/react-native/pull/50704
Is there any fix? The fix above does usually does not work
This is a real struggle. I have just upgraded on "0.76.8" and now I am seeing this issue in various places of a really large app. Are we going to create a patch for this? Is anyone looking into this? Switching off new architecture does not sound very promising, but it works then.
@sarthak-cars24
I was able to to fix this by wrapping Modal with View
import { Modal as RNModal } from "react-native";
<ThemedView
style={{
width: "100%",
height: "100%",
position: "absolute",
backgroundColor: "transparent",
}}
>
<RNModal
visible={isOpen}
transparent
animationType="fade"
statusBarTranslucent
{...rest}
onOrientationChange={() => {}}
onRequestClose={onClose}
supportedOrientations={[
"portrait",
"portrait-upside-down",
"landscape-left",
"landscape-right",
]}
>
{content}
</RNModal>
</ThemedView>
Hey @tarasovladislav Thanks for the super quick reply. Let me try this out, can you also explain how did this solve the issue?
With this workaround Modal content is always appearing correctly. Before it was in the top left corner or positioned correctly but without correctly rendered elements.
Let me know if this worked for you @sarthak-cars24
Hey @tarasovladislav Thanks for the fix, I can confirm this workaround works.
Created a small patch file for React Native v0.76.9, I hope its helpful
diff --git a/node_modules/react-native/Libraries/Modal/Modal.js b/node_modules/react-native/Libraries/Modal/Modal.js
index f0cb214..40a10f2 100644
--- a/node_modules/react-native/Libraries/Modal/Modal.js
+++ b/node_modules/react-native/Libraries/Modal/Modal.js
@@ -280,6 +280,7 @@ class Modal extends React.Component<Props, State> {
};
return (
+ <View style={styles.modal}>
<RCTModalHostView
animationType={animationType}
presentationStyle={presentationStyle}
@@ -307,6 +308,7 @@ class Modal extends React.Component<Props, State> {
</ScrollView.Context.Provider>
</VirtualizedListContextResetter>
</RCTModalHostView>
+ </View>
);
}
@@ -320,6 +322,7 @@ const side = I18nManager.getConstants().isRTL ? 'right' : 'left';
const styles = StyleSheet.create({
modal: {
position: 'absolute',
+ backgroundColor: 'transparent',
},
container: {
/* $FlowFixMe[invalid-computed-prop] (>=0.111.0 site=react_native_fb) This
Thanks for the reproducer @AndreiCalazans The fix should be this one:
- https://github.com/facebook/react-native/pull/51048
I can confirm it does fix the layout issue. Thank you:
https://github.com/user-attachments/assets/dc62d90b-3ae1-4f8c-b999-f2a29b21747b
@tarasovladislav Worked for me as well 👍🏼 You are lifesaver, Thank you buddy
react-native: 0.76.9
LMAO, I just upgraded react-native to v0.76.9 and I'm so confused why all my modal is broken.
Thanks @tarasovladislav
I have applied the solution which @tarasovladislav is give still my issue is not fixed i am using react-native 0.78.2 version below i have attached my code:
import React, { useEffect } from "react";
import { View, StyleSheet, Text, Modal } from "react-native";
import Animated, {
useSharedValue,
useAnimatedStyle,
withRepeat,
withTiming,
cancelAnimation,
Easing,
} from "react-native-reanimated";
import { scale } from "react-native-size-matters";
import appFonts from "../utils/theme";
import Colors from "../theme/colors";
const Loader = ({
size = scale(40),
color = Colors.white,
loading,
text = "Loading...",
}) => {
const rotation = useSharedValue(0);
useEffect(() => {
if (loading) {
rotation.value = withRepeat(
withTiming(360, {
duration: 400,
easing: Easing.linear,
}),
-1,
false
);
} else {
cancelAnimation(rotation);
rotation.value = 0;
}
return () => {
cancelAnimation(rotation);
rotation.value = 0;
};
}, [loading]);
const animatedStyle = useAnimatedStyle(() => ({
transform: [{ rotate: `${rotation.value}deg` }],
}));
return (
<View
style={{
width: "100%",
height: "100%",
position: "absolute",
backgroundColor: "transparent",
}}
>
<Modal
transparent
visible={loading}
animationType="fade"
statusBarTranslucent
>
<View style={styles.modalBackground}>
<View style={styles.loaderView}>
<Animated.View
style={[
styles.spinner,
animatedStyle,
{
width: size,
height: size,
borderRadius: size / 2,
borderTopColor: color,
borderRightColor: color,
borderBottomColor: "#ffffff40",
borderLeftColor: "#ffffff10",
},
]}
/>
<Text style={styles.text}>{text}</Text>
</View>
</View>
</Modal>
</View>
);
};
const styles = StyleSheet.create({
modalBackground: {
flex: 1,
backgroundColor: Colors.transparentColor,
justifyContent: "center",
alignItems: "center",
},
loaderView: {
backgroundColor: Colors.black500,
padding: scale(25),
borderRadius: scale(10),
alignItems: "center",
elevation: scale(10),
shadowColor: Colors.white,
shadowOffset: { width: scale(0), height: scale(0) },
shadowOpacity: scale(0.7),
shadowRadius: scale(10),
},
spinner: {
borderWidth: scale(4),
borderStyle: "solid",
},
text: {
color: Colors.white,
marginTop: scale(10),
fontFamily: appFonts.poppins_bold,
fontSize: scale(12),
},
});
export default Loader;
我也遇到了这个问题
For those still having this issue, you can try this one: https://medium.com/@varunk.cet1995/solving-the-ios-modal-flicker-issue-in-react-native-8fa447731f4b
Works well with android, too.
Looks like the fix is on 0.79.6 only. @cortinico Why is it not available on 0.81 or 0.82? Is this expected?
Looks like the fix is on 0.79.6 only. @cortinico Why is it not available on 0.81 or 0.82? Is this expected?
It's definitely included in 0.81 and 0.82 as well
For those still having this issue, you can try this one: https://medium.com/@varunk.cet1995/solving-the-ios-modal-flicker-issue-in-react-native-8fa447731f4b
Works well with android, too.
for the ones who have an issue with the close since they don't use the exact hardware button and they use a custom button, a useEffect will do the job
useEffect(() => {
if (!visible) {
setIsModalContentVisible(false);
}
}, [visible]);