Skip to content
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

Header back button missing when navigating from root to a nested stack where root-stack has headerShown set to false #1460

Open
5 of 7 tasks
hirbod opened this issue May 29, 2022 · 23 comments
Labels
Platform: Android This issue is specific to Android Platform: iOS This issue is specific to iOS Platform: Web This issue is specific to web Repro provided A reproduction with a snack or repo is provided

Comments

@hirbod
Copy link
Contributor

hirbod commented May 29, 2022

Description

Hi @WoLewicki, I have following issue.

Following scenario (pseudo):

   RootStack (headerShown: false)
       BottomTabsNavigator
       StackNavigator1 (headerShown: true, since I want to maintain the own stack)
       StackNavigator2 (headerShown: true, since I want to maintain the own stack)
       StackNavigator3 (headerShown: true, since I want to maintain the own stack)

These stacks are placed inside root stack but not in BottomTabs, since we want them to be placed above the BottomTabs

No issues so far. The real issue is that since we've disabled headerShown for RootStack, because our child stacks need to maintain there own header, the back button is missing when I navigate to StackNavigator1, 2 or 3.

I made some tests (canGoBack() and goBack/pop). All methods work, canGoBack returns true. The navigator is actually aware that it CAN go back, but you're disabling the back button at this place. I also talked with @satya164 and tested the JSStack and it is handled correctly there, where the back button won't be removed.

Currently, I am forced to use headerLeft and insert my own back button. While basically no big deal, the real issue is that headerLeft position is not the exact same position as the native back button (native back button is like 8px from left, while headerLeft starts at around 20px) and that when you try to achieve the same look across the app, you would need to to apply a left: -12. The problem with that is again, that the back button gets cut-off while animating the header between navigation. Thats an issue for itself but this also describes why I don't want to add headerLeft manually.

The issue does not appear when we enable the header in RootStack, but that is not what we want. We want that each child-nest-stack to handle its own header and logic.

Screenshots

Steps To Reproduce

  1. I already described everything
  2. There is a snack available

Expected behavior

Native back button should appear, should be handled like in the JS-Stack.

Actual behavior

Back button is hidden, even though canGoBack returns true

Reproduction

https://snack.expo.dev/@hirbod/native-stack-header-issues---back-button-missing

I made this snack interactive. Please click through it and take notes on the text. While reproducible in web as well, please also test on iOS and Android, there are extra issues.

Platform

  • iOS
  • Android
  • Web
  • Windows
  • tvOS

Workflow

  • Managed workflow
  • Bare workflow

Package versions

package version
react-native 0.68.2
@react-navigation/native 6
@react-navigation/native-stack 6
react-native-screens 3.13
react-native-safe-area-context 4.2.4
react-native-gesture-handler 2.4.2
react-native-reanimated 2.8.0
expo 45
@github-actions github-actions bot added Repro provided A reproduction with a snack or repo is provided Platform: iOS This issue is specific to iOS Platform: Android This issue is specific to Android Platform: Web This issue is specific to web labels May 29, 2022
@WoLewicki
Copy link
Member

Does the back button not appear on Android too? On iOS I am afraid it is not possible to achieve the native header back button in such case since it is a native prop based on if we are deeper in stack and since the nested stack has only one screen pushed at the beginning, there is nowhere to go back in it. JS stack adds does not use native header so it can add such button on demand.

@WoLewicki
Copy link
Member

It looks like on Android the back button is visible:
image

@hirbod
Copy link
Contributor Author

hirbod commented Jun 1, 2022

You're right, android works. iOS not. But the same goes for web.

To be honest, I am pretty confident that this is doable on iOS. The stack is aware that it can return, even gestures do work. I can't imagine that there is no way to make the header show that icon.

@hirbod
Copy link
Contributor Author

hirbod commented Jun 1, 2022

And what is still unanswered: why is header left and header right wrongly positioned and gets cut off when changing the left value while animation. The insets applied are not correct

@satya164
Copy link
Collaborator

satya164 commented Jun 2, 2022

The stack is aware that it can return, even gestures do work

The gesture likely works because the screen the stack is nested in is aware that it can go back with a gesture and it handles the gesture, but the nested stack itself isn't aware.

@hirbod
Copy link
Contributor Author

hirbod commented Jun 2, 2022

So you think it is not possible to make the nested stack aware of it (maybe a flag which tells it to show the back button unless headerLeft is set)

@satya164
Copy link
Collaborator

satya164 commented Jun 2, 2022

Unless the native UINavigationController supports it then there's no other way than a custom header (or fix that issue you have with the custom back button if possible)

@hirbod
Copy link
Contributor Author

hirbod commented Jun 3, 2022

Fixing the insets or clipping of headerLeft and headerRight would be indeed an feasible solution

@maxckelly
Copy link

Also experiencing this issue. Any help would be greatly appreciated if it's possible.

@hirbod
Copy link
Contributor Author

hirbod commented Jun 12, 2022

@WoLewicki as talked at appjsconf, here is the small "hint/comment/ping" regarding the inset issue. :)
Once again, was a pleasure to meet you in person!

@WoLewicki
Copy link
Member

I will try to look into it as fast as possible, hopefully all Fabric issues in the repo are gone soon 😅 It was great to meet one of the main contributors to the library too!

@gui-grana
Copy link

I'm upgrading React Navigation from version 3 to 6 and facing the same issue. Any updates about this fix or hints about what to do?

satya164 added a commit to react-navigation/react-navigation that referenced this issue Aug 17, 2022
Currently when a Native Stack is nested in another Stack, it doesn't respect the
parent navigation's back stack. This change makes a few adjustments so that if
the parent has a back stack:

- If the user specifies a custom back button, the `canGoBack` and `label`
parameters will now receive the proper data so they can render a back button in
nested stack.
- If JS stack is nested inside a Native stack, it'll now respect the parent's
back stack and show a back button.
- On Web, Native stack nested inside or Native or JS stack will show a back
button.
- On Android, Native Stack nested inside Native stack will show a back button -
since the back button is handled natively, we can't make it show when Native
Stack is nested inside JS Stack
- On iOS, JS stack nested inside Native stack will show a back button - since the
back button is handled natively, we can't make it show when Native Stack is
nested inside JS or Native Stack (see
software-mansion/react-native-screens#1460)

starting # with '#' will be ignored, and an empty message aborts the commit.
satya164 added a commit to react-navigation/react-navigation that referenced this issue Aug 22, 2022
Currently, when a Native Stack is nested in another Stack, it doesn't respect the
parent navigation's back stack. This change makes a few adjustments so that if
the parent has a back stack:

- If the user specifies a custom back button, the `canGoBack` and `label`
parameters will now receive the proper data so they can render a back button in
nested stack.
- If JS stack is nested inside a Native stack, it'll now respect the parent's
back stack and show a back button.
- On Web, Native stack nested inside or Native or JS stack will show a back
button.
- On Android, Native Stack nested inside Native stack will show a back button -
since the back button is handled natively, we can't make it show when Native
Stack is nested inside JS Stack
- On iOS, JS stack nested inside Native stack will show a back button - since the
back button is handled natively, we can't make it show when Native Stack is
nested inside JS or Native Stack (see
software-mansion/react-native-screens#1460)
@evgenyshenets91
Copy link

evgenyshenets91 commented Apr 28, 2023

use @react-navigation/stack instead. it works pretty well! For some reasons @react-navigation/native-stack doesn't display the back button even if it returns canGoBack equals true.

@hirbod
Copy link
Contributor Author

hirbod commented Apr 28, 2023

@evgenyshenets91, using the js-stack is not a recommended approach. The native-stack is unbeatable in terms of performance, especially when paired with React Native Reanimated's new shared-element API that requires native-stack. Therefore, you should not compromise on performance and opt for the native-stack instead.

@jiroscripts
Copy link

@hirbod Did you find a temporary fix for this ?

@hirbod
Copy link
Contributor Author

hirbod commented May 17, 2023

Well, the only solution we had at the end was to use custom headerLeft everywhere to have the same look and feel and not rely on the native buttons. @thibaultcapelli

@jiroscripts
Copy link

Thanks for the response :)
So I suppose you need to check canGoBack ?

@hirbod
Copy link
Contributor Author

hirbod commented May 17, 2023

We used canGoBack in most of our checks, but that value can be inaccurate as it is based on how the stack was built, which was the primary issue in the first place. So you might be able to go back, even if canGoBack is false.

@evgenyshenets
Copy link

Well, the only solution we had at the end was to use custom headerLeft everywhere to have the same look and feel and not rely on the native buttons. @thibaultcapelli

Yep, I have already reworked the solution to custom header, which include Header as parent and header lest at props.

Tried only headerleft + header back button from react-navigation/elements, but it integrated with extra margin from the left(seems that it added by header under the hood).

@sirusbaladi
Copy link

sirusbaladi commented Mar 22, 2024

still an issue, a big one in terms of usability for users.

@samkass
Copy link

samkass commented Aug 15, 2024

Two years later and this rather fundamental issue is still unresolved? It seems the most straightforward workaround is to switch to @react-navigation/stack until expo-router is a little more mature?

@satya164
Copy link
Collaborator

fundamental issue is still unresolved

PRs are welcome

@WKampel
Copy link

WKampel commented Dec 18, 2024

How are people developing apps with this massive issue present? It feels like I'm missing something

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Platform: Android This issue is specific to Android Platform: iOS This issue is specific to iOS Platform: Web This issue is specific to web Repro provided A reproduction with a snack or repo is provided
Projects
None yet
Development

No branches or pull requests