Closed lnmunhoz closed 1 month ago
I cannot repro your issue either on a simulator or physical device. Upgrade packages to the newest version. Is the issue still present then? If so, please try to write which steps to take for the issue to occur.
Yes, I just tried again and the issue is still present. I did a fresh install and the issue persisted. Have you tried the repo I've sent?
The steps are simple:
To create the stack I am using createNativeStackNavigator
from react-native-screens/native-stack
.
I created a snack to reproduce but also not being able to make it happen there:
The thing is, I am using a stack created by createNativeStackNavigator
inside a stack from createStackNavigator
.
I wanted to have parts of my app using the native stack for more simple screens where I don't need to manipulate the header too much, and others the js based stack so I can migrate incrementally.
Is that an issue or should work fine?
I cloned your project and also made a bare react-native project. The issue exists only while opening it through Expo Client. This means that the version of RNScreens in the current Expo Client is having the bug since it has RNScreens in version 2.0.0-alpha.12. Can you repro it that way to prove if it is right?
@lnmunhoz can I close it then? Is your issue solved?
Let me try to reproduce one more time so we can figure out why it was happening.
I will update here in a couple hours.
This is happens in bare RN project as well, so I doubt it has anything to do with Expo
@Deepp0925 does it happen with the newest RNScreens version: 2.4.0?
Yes sir
I have a workaround if it's a blocker for anyone here https://github.com/react-navigation/react-navigation/issues/6746#issuecomment-583897436:
As a workaround I show the Icon after a few ms:
const [shouldRenderIcon, setShouldRenderIcon] = useState(false) useEffect(() => { const nbr = setTimeout(() => setShouldRenderIcon(true), 200) return () => clearTimeout(nbr) }, []) return shouldRenderIcon ? <MyIcon /> : null
I can also confirm that this bug still happens on react-native-screens@2.40
and react-native@0.62
.
Hey @WoLewicki, do you want me to setup a sample project, showing this issue? Here's some screenshots demonstrating the problem:
This first one, is just adding a 44x44 Touchable button as the headerRight
- you can see it's quite far to the left.
If I inspect the element, you can see it's 44x44:
If I add a marginRight: -20
, it does "fix" the alignment, but not the issue itself.
Now if I inspect the element, you can see it's only 24px
wide, so almost half of the button is cropped and not easy to tap.
It feels like this extra 20px
on the right side added by the native wrapper is causing the problem - if that space would be removed entirely the problem would be solved. The back button works this way if you inspect it:
Using a custom compontent in headerCenter is affected by the same bug/problem...
@osdnk
same for me
This happens almost everytime I start the app, this really should be fixed.
I believe it is the same issue as #322. Can you try the workaround submitted there and see if it works correctly?
same for me
same for me too
This is happening to me also with headerCenter and headerRight only in iOS, my custom component is wrongly positioned. It only displays correctly when the default back button is present.
Same problem Im having
const Stack = createNativeStackNavigator();
const AccountsScreen = () => {
return <Stack.Navigator screenOptions={(props) => ({
headerRight: () => <HeaderRight {...props} />,
})}>
...
interface Props { navigation?: NavigationContainerRef; } export const HeaderRight = (props: Props) => { const dispatch = useDispatch(); const {navigation} = props; return <TouchableOpacity onPress={() => dispatch(lock())}> <Text style={{color: 'red'}}>test }
Sometimes the Text gets pushed off screen in ios, RN .62 with latest React Navigation.
Same here using Expo SDK v38
, which relies on ~2.9.0
.
+1
Closed https://github.com/software-mansion/react-native-screens/issues/571 for this as seems to be related. I shouldn't be the one to dictate priority but this seems really important, it's really not ideal to have production apps experience this.
Also I have a feeling mentioning expo is not relevant, I experience this consistently without.
Can you check if #600 resolves the issue and if it does not introduce other unwanted behaviors?
@WoLewicki I've been testing #600 in my app (where I could occasionally reproduce the issue) and haven't seen it since I installed your PR. Haven't seen any sort of regression either.
So, from my perspective, it looks good!
@FrankFundel can you check if #613 resolves your problem introduced in #600? Also, @spencercarli can you check if it does not destroy the good behavior of #600? @kyle-ssg @lnmunhoz @matt-oakes can you check if #600 + #613 resolve the bugs you discovered?
This has been on my todo for a few days, I'll prioritise testing this in the evening @WoLewicki, thanks for letting me know again.
@WoLewicki this does not fix my problem :(
@FrankFundel can you provide a repo/snack that shows the problem then?
@WoLewicki This 100% fixes my issue!
My replication is very straight forward, just do something along the lines of this:
<Stack.Screen ...
initialParams={{
screenOptions: {
headerCenter: ()=> <ReactNative.Text>Loading</ReactNative.Text>,
}
}}
/>
Then in the screen:
useLayoutEffect(() => {
if (route?.params?.screenOptions) {
navigation.setOptions(route.params.screenOptions);
}
}, [navigation, route]);
Before
After
@WoLewicki When I apply #600 the header elements render perfectly 👌, but screens in nested navigators (e.g. modals) won't render until after the transition. #613 appears to address the latter issue, but #613 regresses the header element rendering 😞
@nickyleach What does #613 it regress exactly? The elements don't align the way they should all the time?
@WoLewicki Yeah, in my testing the combination of #600 and #613 seems like the same behavior as what's currently in 2.10.1
Can you provide a repo in which applying these changes show the wrong aligning again?
@WoLewicki It is still happening with 2.11.0
@happyfloat can you provide a repo/snack with minimal configuration needed to reproduce the issue?
@WoLewicki It's on my todo list. Hopefully by Monday next week. Including the other modal bug, if I can reproduce everything.
Hey @WoLewicki,
Here's a MVCE (minimally viable complete example) of the issue: Repo Issue with GIF
I believe this represents the base issue where a custom header button disappears on rotation. I've had some success following some of the other fixes around, like using a time out, or listening to window dimensions changes to try to force a re-render, but those are all hacks on top of this base problem here, and none of them solve the problem entirely.
Attaching gif here below too:
I'm running it on a iPad, but it seems to happen on an iPhone as well.
Let me know if you need anything else.
@zibs the issue with items disappearing on rotation is discussed in #528. This issue is about positioning the header items on load, which I believe was fixed. You can check the workaround proposed in there (#644), but I am aware it is not a perfect one.
Hey @WoLewicki thanks for the follow up. Can you check out this updated gif and see if you have any insights? I've integrated the workaround you proposed in #644 into my repo, and it seems to partly fix one issue, but the not issue I'm hunting down in particular:
You can see in this gif that it works fine now while rotating on screen 1, but you if go to screen 2, rotate there, and then come back to screen1 (happens at the end of the gif), the header button is gone again.
Like I said, the repo is updated if you want to run it, and it's applying your patch when built.
@zibs can you post this comment in #528 to keep the discussion there? Also, you can try to move all the code inside this added method to a new method, and then call it in RNSScreen
viewWillAppear
, maybe it will fix the issue for when coming back from another screen. Please comment if you need more help with applying this.
Having the same issue on iPhone.
I only see it happening on release mode and it doesn't happen always or in all the screens.
Worked it around by setting headerRight as an empty Text on the screen definition.
const ScreenComponent = ({ navigation }) => {
useEffect(() => {
navigation.setOptions({
headerRight: () => (
<TouchableOpacity>
<Text>Button</Text>
</TouchableOpacity>
)
}, []);
return <View>...</View>;
}
const App = () => (
<Stack.Navigator>
<Stack.Screen
name="ScreenName"
component={ScreenComponent}
options={{
headerRight: () => <Text> </Text>,
}}
/>
</Stack.Navigator>
);
package.json
{
"name": "App",
"version": "2.0.0",
"private": true,
"scripts": {
"android": "react-native run-android",
"ios": "react-native run-ios",
"start": "react-native start",
"test": "jest",
"lint": "eslint .",
"postinstall": "patch-package && npx jetify",
"relay": "relay-compiler --src ./src --schema ./schema.graphql",
"update_schema": "node scripts/update_schema.js"
},
"dependencies": {
"@expo/react-native-action-sheet": "^3.8.0",
"@invertase/react-native-apple-authentication": "^1.1.2",
"@react-native-community/async-storage": "^1.11.0",
"@react-native-community/blur": "^3.6.0",
"@react-native-community/cookies": "^4.0.0",
"@react-native-community/hooks": "^2.6.0",
"@react-native-community/masked-view": "^0.1.10",
"@react-native-community/netinfo": "^5.9.5",
"@react-native-firebase/app": "^8.2.0",
"@react-native-firebase/messaging": "^7.5.0",
"@react-navigation/bottom-tabs": "^5.9.2",
"@react-navigation/drawer": "^5.9.3",
"@react-navigation/native": "^5.7.6",
"@react-navigation/stack": "^5.9.3",
"@rnhooks/async-storage": "^0.0.1",
"@rnhooks/keyboard": "^0.0.3",
"axios": "^0.19.2",
"babel-relay-plugin": "^0.11.0",
"cookie": "^0.4.1",
"formik": "^2.1.5",
"jetifier": "^1.6.6",
"lodash": "^4.17.20",
"moment": "^2.29.0",
"patch-package": "^6.2.2",
"postinstall-postinstall": "^2.1.0",
"react": "16.13.1",
"react-native": "0.63.3",
"react-native-background-fetch": "^3.1.0",
"react-native-config": "^1.3.3",
"react-native-device-info": "^5.6.3",
"react-native-elements": "^2.3.2",
"react-native-geocoding": "^0.4.0",
"react-native-geolocation-service": "^5.0.0",
"react-native-gesture-handler": "^1.8.0",
"react-native-gifted-chat": "^0.16.3",
"react-native-google-fit": "^0.12.2",
"react-native-image-crop-picker": "^0.35.0",
"react-native-inappbrowser-reborn": "^3.4.0",
"react-native-intercom": "^17.0.0",
"react-native-localize": "^1.4.1",
"react-native-offline": "^5.7.0",
"react-native-permissions": "^2.1.5",
"react-native-raw-bottom-sheet": "^2.2.0",
"react-native-reanimated": "^1.13.1",
"react-native-safe-area-context": "^3.1.7",
"react-native-screens": "^2.11.0",
"react-native-side-menu": "^1.1.3",
"react-native-vector-icons": "^7.0.0",
"react-native-version-number": "^0.3.6",
"react-native-webview": "^10.3.2",
"react-relay": "^10.0.1",
"reanimated-bottom-sheet": "^1.0.0-alpha.22",
"relay-runtime": "^10.0.1",
"rn-apple-healthkit": "^0.8.0",
"rollbar-react-native": "^0.9.1",
"swr": "^0.2.3",
"url": "^0.11.0",
"yup": "^0.29.3"
},
"devDependencies": {
"@babel/core": "^7.10.4",
"@babel/runtime": "^7.10.4",
"@react-native-community/eslint-config": "^2.0.0",
"babel-jest": "^26.1.0",
"babel-plugin-relay": "^10.0.1",
"eslint": "^7.4.0",
"graphql": "^15.3.0",
"jest": "^26.1.0",
"metro-react-native-babel-preset": "^0.60.0",
"react-test-renderer": "16.13.1",
"relay-compiler": "^10.0.1",
"relay-config": "^10.0.1"
},
"jest": {
"preset": "react-native"
}
}
It seems there's been a bit of a regression here. I am seeing the header title being randomly positioned to the right when using NativeStack from react-navigation. Opening the view debugger in Xcode shows the width as 0, which would explain why it's "to the right", it's centered with the width being 0 and shows the overflow.
$ grep react-native-screens package.json
"react-native-screens": "^3.13.1",
$ grep react-native package.json
...
"react-native": "0.67.4",
...
$ grep react-navigation package.json
"@react-navigation/bottom-tabs": "^6.3.1",
"@react-navigation/elements": "^1.3.3",
"@react-navigation/native": "^6.0.10",
"@react-navigation/native-stack": "^6.6.1",
I'm experiencing the same. Only on a real device in release and not on a simulator.
Since you posted this workaround 2 years ago, I ask you: did it really work?
Having the same issue on iPhone.
I only see it happening on release mode and it doesn't happen always or in all the screens.
Worked it around by setting headerRight as an empty Text on the screen definition.
const ScreenComponent = ({ navigation }) => { useEffect(() => { navigation.setOptions({ headerRight: () => ( <TouchableOpacity> <Text>Button</Text> </TouchableOpacity> ) }, []); return <View>...</View>; } const App = () => ( <Stack.Navigator> <Stack.Screen name="ScreenName" component={ScreenComponent} options={{ headerRight: () => <Text> </Text>, }} /> </Stack.Navigator> );
package.json
{ "name": "App", "version": "2.0.0", "private": true, "scripts": { "android": "react-native run-android", "ios": "react-native run-ios", "start": "react-native start", "test": "jest", "lint": "eslint .", "postinstall": "patch-package && npx jetify", "relay": "relay-compiler --src ./src --schema ./schema.graphql", "update_schema": "node scripts/update_schema.js" }, "dependencies": { "@expo/react-native-action-sheet": "^3.8.0", "@invertase/react-native-apple-authentication": "^1.1.2", "@react-native-community/async-storage": "^1.11.0", "@react-native-community/blur": "^3.6.0", "@react-native-community/cookies": "^4.0.0", "@react-native-community/hooks": "^2.6.0", "@react-native-community/masked-view": "^0.1.10", "@react-native-community/netinfo": "^5.9.5", "@react-native-firebase/app": "^8.2.0", "@react-native-firebase/messaging": "^7.5.0", "@react-navigation/bottom-tabs": "^5.9.2", "@react-navigation/drawer": "^5.9.3", "@react-navigation/native": "^5.7.6", "@react-navigation/stack": "^5.9.3", "@rnhooks/async-storage": "^0.0.1", "@rnhooks/keyboard": "^0.0.3", "axios": "^0.19.2", "babel-relay-plugin": "^0.11.0", "cookie": "^0.4.1", "formik": "^2.1.5", "jetifier": "^1.6.6", "lodash": "^4.17.20", "moment": "^2.29.0", "patch-package": "^6.2.2", "postinstall-postinstall": "^2.1.0", "react": "16.13.1", "react-native": "0.63.3", "react-native-background-fetch": "^3.1.0", "react-native-config": "^1.3.3", "react-native-device-info": "^5.6.3", "react-native-elements": "^2.3.2", "react-native-geocoding": "^0.4.0", "react-native-geolocation-service": "^5.0.0", "react-native-gesture-handler": "^1.8.0", "react-native-gifted-chat": "^0.16.3", "react-native-google-fit": "^0.12.2", "react-native-image-crop-picker": "^0.35.0", "react-native-inappbrowser-reborn": "^3.4.0", "react-native-intercom": "^17.0.0", "react-native-localize": "^1.4.1", "react-native-offline": "^5.7.0", "react-native-permissions": "^2.1.5", "react-native-raw-bottom-sheet": "^2.2.0", "react-native-reanimated": "^1.13.1", "react-native-safe-area-context": "^3.1.7", "react-native-screens": "^2.11.0", "react-native-side-menu": "^1.1.3", "react-native-vector-icons": "^7.0.0", "react-native-version-number": "^0.3.6", "react-native-webview": "^10.3.2", "react-relay": "^10.0.1", "reanimated-bottom-sheet": "^1.0.0-alpha.22", "relay-runtime": "^10.0.1", "rn-apple-healthkit": "^0.8.0", "rollbar-react-native": "^0.9.1", "swr": "^0.2.3", "url": "^0.11.0", "yup": "^0.29.3" }, "devDependencies": { "@babel/core": "^7.10.4", "@babel/runtime": "^7.10.4", "@react-native-community/eslint-config": "^2.0.0", "babel-jest": "^26.1.0", "babel-plugin-relay": "^10.0.1", "eslint": "^7.4.0", "graphql": "^15.3.0", "jest": "^26.1.0", "metro-react-native-babel-preset": "^0.60.0", "react-test-renderer": "16.13.1", "relay-compiler": "^10.0.1", "relay-config": "^10.0.1" }, "jest": { "preset": "react-native" } }
Since you posted this workaround 2 years ago, I ask you: did it really work?
Having the same issue on iPhone. I only see it happening on release mode and it doesn't happen always or in all the screens. Worked it around by setting headerRight as an empty Text on the screen definition.
const ScreenComponent = ({ navigation }) => { useEffect(() => { navigation.setOptions({ headerRight: () => ( <TouchableOpacity> <Text>Button</Text> </TouchableOpacity> ) }, []); return <View>...</View>; } const App = () => ( <Stack.Navigator> <Stack.Screen name="ScreenName" component={ScreenComponent} options={{ headerRight: () => <Text> </Text>, }} /> </Stack.Navigator> );
package.json
{ "name": "App", "version": "2.0.0", "private": true, "scripts": { "android": "react-native run-android", "ios": "react-native run-ios", "start": "react-native start", "test": "jest", "lint": "eslint .", "postinstall": "patch-package && npx jetify", "relay": "relay-compiler --src ./src --schema ./schema.graphql", "update_schema": "node scripts/update_schema.js" }, "dependencies": { "@expo/react-native-action-sheet": "^3.8.0", "@invertase/react-native-apple-authentication": "^1.1.2", "@react-native-community/async-storage": "^1.11.0", "@react-native-community/blur": "^3.6.0", "@react-native-community/cookies": "^4.0.0", "@react-native-community/hooks": "^2.6.0", "@react-native-community/masked-view": "^0.1.10", "@react-native-community/netinfo": "^5.9.5", "@react-native-firebase/app": "^8.2.0", "@react-native-firebase/messaging": "^7.5.0", "@react-navigation/bottom-tabs": "^5.9.2", "@react-navigation/drawer": "^5.9.3", "@react-navigation/native": "^5.7.6", "@react-navigation/stack": "^5.9.3", "@rnhooks/async-storage": "^0.0.1", "@rnhooks/keyboard": "^0.0.3", "axios": "^0.19.2", "babel-relay-plugin": "^0.11.0", "cookie": "^0.4.1", "formik": "^2.1.5", "jetifier": "^1.6.6", "lodash": "^4.17.20", "moment": "^2.29.0", "patch-package": "^6.2.2", "postinstall-postinstall": "^2.1.0", "react": "16.13.1", "react-native": "0.63.3", "react-native-background-fetch": "^3.1.0", "react-native-config": "^1.3.3", "react-native-device-info": "^5.6.3", "react-native-elements": "^2.3.2", "react-native-geocoding": "^0.4.0", "react-native-geolocation-service": "^5.0.0", "react-native-gesture-handler": "^1.8.0", "react-native-gifted-chat": "^0.16.3", "react-native-google-fit": "^0.12.2", "react-native-image-crop-picker": "^0.35.0", "react-native-inappbrowser-reborn": "^3.4.0", "react-native-intercom": "^17.0.0", "react-native-localize": "^1.4.1", "react-native-offline": "^5.7.0", "react-native-permissions": "^2.1.5", "react-native-raw-bottom-sheet": "^2.2.0", "react-native-reanimated": "^1.13.1", "react-native-safe-area-context": "^3.1.7", "react-native-screens": "^2.11.0", "react-native-side-menu": "^1.1.3", "react-native-vector-icons": "^7.0.0", "react-native-version-number": "^0.3.6", "react-native-webview": "^10.3.2", "react-relay": "^10.0.1", "reanimated-bottom-sheet": "^1.0.0-alpha.22", "relay-runtime": "^10.0.1", "rn-apple-healthkit": "^0.8.0", "rollbar-react-native": "^0.9.1", "swr": "^0.2.3", "url": "^0.11.0", "yup": "^0.29.3" }, "devDependencies": { "@babel/core": "^7.10.4", "@babel/runtime": "^7.10.4", "@react-native-community/eslint-config": "^2.0.0", "babel-jest": "^26.1.0", "babel-plugin-relay": "^10.0.1", "eslint": "^7.4.0", "graphql": "^15.3.0", "jest": "^26.1.0", "metro-react-native-babel-preset": "^0.60.0", "react-test-renderer": "16.13.1", "relay-compiler": "^10.0.1", "relay-config": "^10.0.1" }, "jest": { "preset": "react-native" } }
It was long ago and my memory doesn't go that far, but If I posted it here it's because it worked.
Can't confirm if it's still doing it though, I don't even remember which app this was for.
this work for me:
useLayoutEffect(() => {
navigation.setOptions({
...
},
})
}, [navigation])
I know this is not the best solution but it worked for me.
headerRight: () => (
<Pressable
onPress={() => {
if (chatroom && chatroom.type === 'one') return;
navigation.navigate('InviteUsers');
}}>
<AddWhite
color={chatroom && chatroom.type !== 'one' ? '#707376' : '#ffffff'}
/>
</Pressable>
),
I was testing the
createNativeStackNavigation
and ended up having this random issue where the component rendered byheaderRight
is being positioned incorrectly sometimes. There's nothing special in my code, I am just rendering a<Button>
fromreact-native
.Here's the source code: https://github.com/lnmunhoz/react-native-experiments/blob/master/react-navigation-examples/examples/NativeNavigation.tsx.
Update
The issue also happens when the
headerLargeTitle
isfalse
.