-
-
Notifications
You must be signed in to change notification settings - Fork 532
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
ios onLayout height & screen content jumping on initial render #1504
Comments
Hey! 👋 It looks like you've omitted a few important sections from the issue template. Please complete Description and Steps To Reproduce sections. |
I can confirm that the same issue happens on Android as well. The issue is due to the presence of a screen header. With a header
The header height is determined from React Navigation's The difference in the screen's height between the It's odd because the header height remains static as seen by the output from Without a header
The As you can see the The issue is exclusive to |
same issue |
this is working, thank you |
This is a workaround I use: const areFloatsEqual = (a: number, b: number, percision: number) => {
return Math.round(a * Math.pow(10, percision)) === Math.round(b * Math.pow(10, percision));
}
const Screen = (props: {
children: ReactNode,
// https://github.com/software-mansion/react-native-screens/issues/1504
workaroundNativeStackNavigatorHeaderBug?: boolean,
}) => {
const { children, workaroundNativeStackNavigatorHeaderBug } = props;
const [correctHeight, setCorrectHeight] = useState<number>();
const [currentHeight, setCurrentHeight] = useState<number>();
const wasCorrectHeightAchieved = useRef(false);
const { height: windowHeight } = Dimensions.get('window');
const headerHeight = useHeaderHeight();
useEffect(() => {
if (!workaroundNativeStackNavigatorHeaderBug) {
return;
}
setCorrectHeight(windowHeight - headerHeight);
}, []);
const shouldRender = (() => {
if (!workaroundNativeStackNavigatorHeaderBug) {
return true;
}
if (wasCorrectHeightAchieved.current) {
return true;
}
if (typeof correctHeight === 'undefined' || typeof currentHeight === 'undefined') {
return false;
}
const percision = 2;
const result = areFloatsEqual(correctHeight, currentHeight, percision);
wasCorrectHeightAchieved.current = result;
return result;
})();
return (
<View
style={{ flex: 1 }}
onLayout={(e) => {
if (!workaroundNativeStackNavigatorHeaderBug) {
return;
}
if (wasCorrectHeightAchieved.current) {
return;
}
setCurrentHeight(e.nativeEvent.layout.height);
}}
>
{
shouldRender &&
children
}
</View>
);
} <NativeStack.Navigator>
<NativeStack.Screen
name='MyScreen'
component={() => {
return (
<Screen workaroundNativeStackNavigatorHeaderBug>
{ /* You stuff goes here... */ }
</Screen>
);
}}
/>
</NativeStack.Navigator> |
same issue |
Having the same issue. I found that it is caused by #222 & #184, which updates the size after it was rendered once.
|
Duplicated from react-navigation/react-navigation#10673 since the bot asked for it.
Description
Current behavior
Using Native Stack navigator and navigating to another screen, which has onLayout listener for the Root element logs:
(tested on iphone XS max)
If I wrap the screen with SafeAreaView, it logs even more onLayoutEvents:
On top of it, on some ios devices I can see that the content gets rendered with the initial height (896) & quickly rerendered with the correct height (the components don't have hardcoded height inside but use flex).
I think the layout jumping depends on JS execution speed (it happens on a production build, but does not happen if enable debug build or do console.warn).
Here is an image showing that content initially gets rendered bigger and then gets to correct height:
Expected behavior
The onLayout should be called with correct layout info the very first time & the screen should not jump on the very first render.
Steps To Reproduce
Reproduction
https://snack.expo.dev/wMSEvt-Vr
Platform
Packages
Environment
The text was updated successfully, but these errors were encountered: