expo icon indicating copy to clipboard operation
expo copied to clipboard

Navigation deep into a different tab's stack does not provide a back button in header. Impossible to "go back" to root of that stack.

Open samskinner32 opened this issue 1 year ago • 16 comments

Minimal reproducible example

https://github.com/samskinner32/sam-router-test

Which package manager are you using? (Yarn is recommended)

npm

If the issue is web-related, please select the bundler (web.bundler in the app.json)

None

Summary

Hi all, hoping for help on an unexpected behavior I'm seeing on a fresh project with a seemingly simple use case.

Basically, I have two tabs: Home and Two. The tab Two is a Stack and holds both an index and a details screen. If I navigate from two/index to two/details via the router (or Link), I get a back button in the header to return to index, as you'd expect.

On home/index I have a button to directly navigate to two/details via <Link href="/two/details".... Ideally, if I press this, I would switch to tab Two, land on the details screen and have a back button in the header to return to the index screen of tab Two.

However, if I press this button without previously viewing the second tab, I land on the details screen WITHOUT a back button. And I now have no possible way to navigate to the index screen of tab Two. If I do view the second tab prior to pressing the button, it acts as I've described in my ideal behavior. (Both of these flows are demonstrated in the video)

This feels wrong to me, but I'd love any input or help to achieve the ideal behavior described. Thanks so much!

File structure is:

\-(tabs)
 | index.tsx
 | _layout.tsx
 |
  \-two
   | index.tsx
   | details.tsx
   | _layout.tsx

https://github.com/expo/expo/assets/53786564/1ad0c231-d6a7-48f2-a5e0-ac903006bce7

Environment

expo-env-info 1.2.0 environment info: System: OS: macOS 14.3 Shell: 5.9 - /bin/zsh Binaries: Node: 21.7.2 - /opt/homebrew/bin/node npm: 10.5.0 - /opt/homebrew/bin/npm Watchman: 2024.04.01.00 - /opt/homebrew/bin/watchman Managers: CocoaPods: 1.15.2 - /opt/homebrew/bin/pod SDKs: iOS SDK: Platforms: DriverKit 23.5, iOS 17.5, macOS 14.5, tvOS 17.5, visionOS 1.2, watchOS 10.5 IDEs: Android Studio: 2023.2 AI-232.10300.40.2321.11567975 Xcode: 15.4/15F31d - /usr/bin/xcodebuild npmPackages: expo: ~51.0.17 => 51.0.17 expo-router: ~3.5.17 => 3.5.17 react: 18.2.0 => 18.2.0 react-dom: 18.2.0 => 18.2.0 react-native: 0.74.2 => 0.74.2 react-native-web: ~0.19.10 => 0.19.12 npmGlobalPackages: eas-cli: 10.0.3 Expo Workflow: managed

samskinner32 avatar Jul 02 '24 19:07 samskinner32

It seems like I can get my expected behavior by setting lazy: true on each of the tabs. Is that the recommended solution here or is there another way to achieve this? Thanks!

samskinner32 avatar Jul 04 '24 01:07 samskinner32

I wanted to bump this as I'm not thrilled with the lazy approach as a fix. Right now my app is lightweight, but in the future, it could introduce poor performance for each tab to be firing off any requests/logic needed on their index screens.

I feel like this is a bug or at least that it's a common enough use case that there should be a recommended approach. Would love to discuss! Thanks!

samskinner32 avatar Aug 14 '24 15:08 samskinner32

same issue

Khalid-Badawi2001 avatar Sep 17 '24 12:09 Khalid-Badawi2001

I am facing the same issue when deeplinking into a screen within a Tab Stack.

LukaszK88 avatar Oct 07 '24 15:10 LukaszK88

Same :( this was first google result

OwenMelbz avatar Oct 26 '24 17:10 OwenMelbz

It´s kinda shocking how poorly all of this is documented, there seem far more people with questions than ones that actually got expo router to work well :(

From a design desicion standpoint it´s quite strange: You have to configure the Naivation to make it look nice, but then also have to deal with all the files being included automatically (kinda the worst of both aprroaches).

thomasf1 avatar Nov 10 '24 13:11 thomasf1

same here ;(

mopcweb avatar Jan 25 '25 21:01 mopcweb

I've ended up linking like router.push('/whatever/page', { withAnchor: true }); when I'm navigating across different tabs - seems to sort it. Not ideal though.

vonkanehoffen avatar Jan 27 '25 17:01 vonkanehoffen

same here X(

exceedsystem avatar Jan 31 '25 18:01 exceedsystem

same why it doesn't have answer yet?

beautyfree avatar Feb 09 '25 21:02 beautyfree

8 months in. I bookmarked this thread. I am still trying to figure out how to solve this problem...

bastischulz avatar Feb 14 '25 09:02 bastischulz

Same here with nested stack structure

d4t06 avatar Feb 22 '25 21:02 d4t06

i was able to solve the problem with expo shared routes, but I don't know how efficient it is.

tahafatih avatar Mar 09 '25 01:03 tahafatih

Similar issue when on Web.

I have the following structure

\-user
 | index.tsx
 | _layout.tsx // tabs, index is "home" page, settings is a layout of stack
 |
  \-settings
   | index.tsx
   | profile.tsx
   | _layout.tsx

When you are on /user/settings/profile and you reload the page there is no back button. If you press the Settings tab icon it doesnt take you back to the index for settings. If you press on home and then the settings tab icon, it just takes you back to the profile page, you cannot actually go back to settings unless you full refresh your page.

Wolfleader101 avatar Mar 14 '25 04:03 Wolfleader101

(I tried on iOS) This can be solved by using the "Shared routes" trick. See

  • https://docs.expo.dev/router/advanced/shared-routes/
  • https://stackoverflow.com/questions/78592895/link-to-a-route-with-expo-router-outside-of-the-current-tab-stack-while-keeping/79076057#79076057

Although I find out that:

  • If I go from page A in tab 1 to page B in tab 2 and back to tab A in page 1 by two <Link>s, I still end up with a page without a back button.
  • If I could be able to edit the stack in https://docs.expo.dev/versions/latest/sdk/router/#router, I may be able to edit the stack and remove the loop. However, it only provide dismiss(count: number) so I cannot read the stack and identify the loop.

ozooxo avatar Mar 15 '25 21:03 ozooxo

(I tried on iOS) This can be solved by using the "Shared routes" trick. See

  • https://docs.expo.dev/router/advanced/shared-routes/
  • https://stackoverflow.com/questions/78592895/link-to-a-route-with-expo-router-outside-of-the-current-tab-stack-while-keeping/79076057#79076057

Although I find out that:

  • If I go from page A in tab 1 to page B in tab 2 and back to tab A in page 1 by two <Link>s, I still end up with a page without a back button.
  • If I could be able to edit the stack in https://docs.expo.dev/versions/latest/sdk/router/#router, I may be able to edit the stack and remove the loop. However, it only provide dismiss(count: number) so I cannot read the stack and identify the loop.

I dont really liuke this solution.

For now i've set my tabs to lazy: false and it seems to have fixed it - albeit, obviously side effects of each page affecting first render.

Wolfleader101 avatar May 01 '25 13:05 Wolfleader101

Same issue, There are two approaches above one with withAnchor: true and another with lazy: false. which would be better for now and why?

naviniitk avatar May 14 '25 11:05 naviniitk

Same issue. I fixed with lazy: false for now.

NathanPo avatar Jun 01 '25 09:06 NathanPo

The same problem occurs when run via deep-link, and this time lazy:false does not solve the problem.

tahafatih avatar Jul 14 '25 18:07 tahafatih

Preferred withAnchor for myself. It resulted in fewer rerenders of the pages in the nested stack compared to lazy: false. Additionally, just seems better to have granular control over which links trigger this behavior rather than making the entire stack unlazy.

GoldenChrysus avatar Sep 19 '25 11:09 GoldenChrysus

Why is this still a problem with expo-router? I also have a minimal reproduction and unstable_settings does not fix it.

alexclinky avatar Sep 26 '25 12:09 alexclinky

Hi All This is expected behavior of react-navigation. When the tab is not lazy loaded, then the Stack in that tab is not created until the tab is focused. Then when the tab is focused it creates stack with only one route (it does not add the index route automatically to the stack). The only way around this is to use lazy: false in the tab options.

If you think this should work differently, please suggest this in react-navigation repository - https://github.com/react-navigation/react-navigation/discussions

@tahafatih For deep-link issue you can use unstable_settings, similarly to how this can be solved with modals - https://docs.expo.dev/router/advanced/modals/#handle-deep-linked-modals

Ubax avatar Oct 03 '25 11:10 Ubax

Same issue here!

itsalysialynn avatar Oct 08 '25 19:10 itsalysialynn