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.
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
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!
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!
same issue
I am facing the same issue when deeplinking into a screen within a Tab Stack.
Same :( this was first google result
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).
same here ;(
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.
same here X(
same why it doesn't have answer yet?
8 months in. I bookmarked this thread. I am still trying to figure out how to solve this problem...
Same here with nested stack structure
i was able to solve the problem with expo shared routes, but I don't know how efficient it is.
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.
(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 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.
Same issue,
There are two approaches above one with withAnchor: true and another with lazy: false. which would be better for now and why?
Same issue.
I fixed with lazy: false for now.
The same problem occurs when run via deep-link, and this time lazy:false does not solve the problem.
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.
Why is this still a problem with expo-router? I also have a minimal reproduction and unstable_settings does not fix it.
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
Same issue here!