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

How to go back to another stack navigator? goBack / pop doesn't go chronologically back! #6434

Closed
mukeshsharma1201 opened this issue Nov 4, 2019 · 53 comments

Comments

@mukeshsharma1201
Copy link

mukeshsharma1201 commented Nov 4, 2019

Current Behavior

I have 2 Stack navigators inside Tab navigator.

Bottom Tab Navigator
- Dashboard Stack Navigator
   - Dashboard Landing screen
   - Dashboard details

- Accounts Stack Navigator
   - Accounts Landing Screen
   - Accounts Details

PROBLEM:

from Dashboard Landing screen, if I do navigation.navigate('AccountDetails'); it takes me to AccountDetails ,

but while going BACK , navigation.goBack() or navigation.pop() takes me to Account Landing screen, instead of Dashboard Landing screen!

Expected Behavior

  • navigation.goBack() should take me to the screen I navigated from!

No Solution available?

I searched StackOverflow and closed issues and I am surprised that there is absolutely no clear answer anywhere!!
Few similar questions and issues:

How to reproduce

Your Environment

software version
react-navigation ^4.0.10
react-native ^0.60.5
node v12.9.1
npm or yarn npm
@mukeshsharma1201
Copy link
Author

If anyone knows any example of achieving this, can you please leave an example here?

@walidvb
Copy link

walidvb commented Nov 8, 2019

Hi, don't take my word for it, but:

To summarise the issue, what you want here is to have a screen accessible from any possible stack. Indeed, navigation pop or goBack only applies to the current stack.

What I did to solve this was to duplicate the screens in every stack that requires it. It's not a very clean solution, but it works(and I couldn't find an better..)
Another option would be to pass the original screen as a param, so you'd know where to go back to(potentially losing history and/or other params).
There's also likely a way to do this by recreating the stack's history, but this sounds very cumbersome!

Happy to hear other thoughts about this!

@uday5162
Copy link

Hii, I was also facing the same problem.
@walidvb I have also tried the duplicate screen (treating them as seperate screens) which means they cannot be interrelated.
and the second solution leads to rerender of the screen.
I think this goBack function should not be restricted to the Current stack

@walidvb
Copy link

walidvb commented Nov 19, 2019

@uday5162 what do you mean by interrelated?

@Zeshan316
Copy link

I've also facing same and completely agree with @walidvb only know this solution as far now.

Bottom Tab Navigator
- Dashboard Stack Navigator
   - Dashboard Landing screen
   - Dashboard details
   - Main Account Landin Screen
   - Main Account Details

- Accounts Stack Navigator
   - Accounts Landing Screen
   - Accounts Details
   - Main Dashboard Landing screen
   - Main Dashboard details

If there is any better solution, it'll be appreciated.

@rwest88
Copy link

rwest88 commented Dec 19, 2019

I've been struggling with this for months, to the point that I pushed screens to a reducer array (using onNavigationStateChange), and replaced the back button with a custom component to pop from that array. Still running into problems as pressing the bottom tab resets the stack and wipes crucial navigation params.

I agree there needs to be a simpler pattern, I've been looking far and wide with no luck

@arabold
Copy link

arabold commented Mar 2, 2020

It seems that "canGoBack" and "goBack" are not sharing the same implementation. In my scenario I have multiple StackNavigation and I jump from within one stack A to the beginning of another stack B using navigate. Both are siblings on the same root app navigation stack - very similar to the original example above. I want to be able to go back from B to the previous one A. While canGoBack returns true, goBack throws an error The action 'GO_BACK' was not handled by any navigator. although the root navigator can clearly handle it. And in fact, if I invoke goBack on the root navigator it works as expected.

This lead me to a workaround in which I simply traverse the stack navigator up until I find one that can actually go back.

  const navigation = useNavigation();
  const goBackSafe = () => {
    // Traverse parent stack until we can go back
    let parent = navigation;
    while (parent.dangerouslyGetState()?.index === 0 && parent.dangerouslyGetParent()) {
      parent = parent.dangerouslyGetParent();
    }
    parent?.goBack();
  };

It's a bit hacky but seems to work. In my opinion goBack() should behave identical to canGoBack(). It doesn't make sense to me that the check returns true while the actual action fails.

Update: Sorry, realized after posting that this bug report is for 4.x while I'm on 5 already. Maybe I need to file a separate one?

@dustinyoste
Copy link

dustinyoste commented Mar 26, 2020

Not ideal, but simple enough, my workaround is to pass the "back" screen to the separate stack screen:

ScreenNavigatingFrom

navigation.navigate('OutsideScreen', { fromScreen: 'ScreenNavigatingFrom' }) }

OutsideScreen

const { fromScreen, navigation } = this.props;
<BackButton
    onPress={ () => (fromScreen ? navigation.navigate(fromScreen) : navigation.goBack()) }
/>
const mapStateToProps = (state, props) => ({
    ...props.navigation.state.params,
});

without redux, should be

const { fromScreen } = this.props.navigation.state.params;

and omit const mapStateToProps = (state, props) => ({ block

@satya164
Copy link
Member

This behaviour is not going to change in v4 since it's a breaking change, but this is no longer the default behaviour in v5. So I'm closing the issue.

@ChechoCZ
Copy link

ChechoCZ commented Jul 3, 2020

As per the documentation, it has the same behavior. It didn't change at all. Any solution for v5?

@sultan-arshi
Copy link

+1
any solution ?

@manikanttiwari
Copy link

Make a separate navigator of single screen 'AccountDetails'. Then It won't go to the 'Account' screen. Hope it'll help you.

@shubhamkes
Copy link

Using v5, wondering still no solution?

@harutyundr
Copy link

Facing the same issue, using v5. In general, we need the same screen to be accessible from multiple locations but with the back action taking back to the screen we can from. As an example can serve any forum/community application, where the same "user profile" page could be accessed:

  1. Directly (e.g. deep linking taking to a user profile, visitor's profile for themselves)
  2. Forum -> Thread screen -> pressing on any user's avatar
  3. What's new -> Thread screen -> pressing on any user's avatar
  4. Search results -> Thread screen -> pressing on any user's avatar
  5. Notifications -> pressing on any user's avatar
  6. Any user profile (accessed using one of the methods above) -> Followers tab -> clicking on one of the followers to see their profile
    etc. etc.

In all these scenarios the expected behavior is to go back to the page from where the user's profile was opened.

For now, I am thinking of making any such "commonly" accessible screen a stack of its own, and include that stack in all top-level stacks of the application. I am not sure if it will work out well or, as I potentially need to include the stacks recursively one in another (profile stack is accessible from the thread stack, but at the same time a thread may be linked directly from a profile and we want to view this stack and be back to the profile we were viewing, so the thread stack should be one of the children of the profile stack...)

I would appreciate any suggestions on how to tackle such cases.

@satya164
Copy link
Member

satya164 commented Nov 5, 2020

I potentially need to include the stacks recursively one in another (profile stack is accessible from the thread stack

Why do you need so many stacks in the first place? If you want chronological navigation, have a single stack navigator instead of nesting multiple stacks which give you nested going back behaviour.

https://reactnavigation.org/docs/nesting-navigators#best-practices-when-nesting

@harutyundr
Copy link

I potentially need to include the stacks recursively one in another (profile stack is accessible from the thread stack

Why do you need so many stacks in the first place? If you want chronological navigation, have a single stack navigator instead of nesting multiple stacks which give you nested going back behaviour.

https://reactnavigation.org/docs/nesting-navigators#best-practices-when-nesting

Thank you for your reply @satya164

My app has quite a usual navigation pattern for a community application. It has a drawer from which different site "sections" are accessible, e.g. News, Forums, Members etc. Each "section" is represented with a Stack, which provides a typical way of accessing the screens, e.g.

  1. Drawer -> Forums stack -> press on a forum -> Thread list -> press on a thread -> Thread screen
  2. Drawer -> News stack -> press on an article -> Article screen
  3. Drawer -> Members stack -> press on a member -> Profile screen

There are, however, interconnections between these stacks, e.g.

  1. Drawer -> .... Thread screen -> press on a user's avatar -> Profile screen of the user
  2. Drawer -> ... -> Article screen -> press on a user's avatar -> Profile screen of the user
    etc.

Even deeper navigation cases are completely possible like
Drawer -> .... Thread screen -> press on a user's avatar -> Profile screen of the user -> press on a thread in "Recent threads" -> Thread screen -> press on another user avatar -> Another profile screen and so on...

And in all these cases users expect to go back to the screen from which they have opened the current screen.

What do you think, could this be achieved using a single stack? If I put all these screens in a single stack, I would need to link to each screen from the drawer as a "top-level" screen, without a "back" button. I am going to give it a try soon and will update here if I succeed or what exactly prevents me from using this approach.

@harutyundr
Copy link

Using a single stack as an only child of the drawer navigator worked for me

 <Drawer.Navigator
            drawerContent={drawerContent}
            initialRouteName={'RootStack'}
            drawerPosition={'left'}
            drawerType={'front'}
            key={'RootDrawer'}
            edgeWidth={0}
            screenOptions={{gestureEnabled: true}}>
      <Drawer.Screen name={'RootStack'} key={'RootStack'} component={RootStackNavigator} />
</Drawer.Navigator>

Now any screen is pushed on top of the stack no matter from which part of the app it is accessed.

The only tricky part was to make the drawer "link" to different stacks. As the drawer navigation has only a single child node, I had to provide my custom DrawerContent, where I put links to every screen I want to be directly accessible from the drawer.

Using navigation.navigate to a screen would cause the screen to be added on top of the stack with a back button, which is not the desired behavior. Using StackActions.replace did replace the current screen with the new screen, but it would use stack transition to change the screens which is not a typical pattern for drawer navigation (it would also not close the drawer).

So, I ended up using navigation.reset(newState) where newState is the full state object I want to reset the navigation to and that worked perfectly.

I hope this helps someone facing the same problem.

@bsmayer
Copy link

bsmayer commented Nov 11, 2020

Is there any clean solution to achieve that?
V5 seems to have the same behavior as V4

@marcpope
Copy link

marcpope commented Dec 30, 2020

Here is how to solve it easily:

On the component, pass a param like 'returnScreen' = 'Home' (or whatever your screen name is) like this:

// navigate to a nested navigator
function gotoStation() {
    navigation.navigate('Stations', {
      screen: 'Station',
      initial: false,
      params: {station: props.station, returnScreen: 'Home'},
    });
  }

Then on your Screen, you can override the button to do whatever you want, here I modify the title and the back button:

function StationScreen({navigation, route}) {
  const station = route.params.station;
  const returnScreen = route.params.returnScreen;
  const title = station.location;
  useEffect(() => {
    navigation.setOptions({
      title: title,
      headerLeft: () => (
        <FontAwesome5.Button
          name="angle-left"
          size={28}
          paddingLeft={20}
          backgroundColor="#00273f"
          color="#fff"
          onPress={() => navigation.navigate(returnScreen)}
        />
      ),
    });
  }, [title]);

...

@GreatAuk
Copy link

Here is how to solve it easily:

On the component, pass a param like 'returnScreen' = 'Home' (or whatever your screen name is) like this:

// navigate to a nested navigator
function gotoStation() {
    navigation.navigate('Stations', {
      screen: 'Station',
      initial: false,
      params: {station: props.station, returnScreen: 'Home'},
    });
  }

Then on your Screen, you can override the button to do whatever you want, here I modify the title and the back button:

function StationScreen({navigation, route}) {
  const station = route.params.station;
  const returnScreen = route.params.returnScreen;
  const title = station.location;
  useEffect(() => {
    navigation.setOptions({
      title: title,
      headerLeft: () => (
        <FontAwesome5.Button
          name="angle-left"
          size={28}
          paddingLeft={20}
          backgroundColor="#00273f"
          color="#fff"
          onPress={() => navigation.navigate(returnScreen)}
        />
      ),
    });
  }, [title]);

...

don't forget Android back button behavior and Ios slip left exit screen ....

@ziyafenn
Copy link

Still no solution for this? Why i can't pop back to the previous screen stack? Manually it's always possible, why there is no function for that.

@mrvirus9898
Copy link

mrvirus9898 commented Mar 29, 2021

Okay fam, I think I have a diagnosed this issue. To many independent Navigation Containers. The following explanation is demonstrated with hooks and typescript, but should work for other RN breeds. Hooks and TS are not a factor here.

TL;DR YOU DONT NEED TO OVERIDE ANYTHING. IN FACT, YOU MAY NEED LESS CODE. REMOVE STACK OR TAB NAVIGATION CONTAINERS THAT ARE INDEPENDENT

Suppose you have a root navigation. That root is going to wrapped in a NavigationContainer.

    <NavigationContainer>
     linking={LinkingConfiguration}
      theme={colorScheme === 'dark' ? DarkTheme : DefaultTheme}>
      <RootNavigator />
    </NavigationContainer>

Later in your code, you are going to stack other navigators. A good example would be a left side drawer. But there is a catch, left side drawer needs to be independent, so you grant it a container with independence. Nothing too crazy about that.

   <NavigationContainer independent={true}>
      <Drawer.Navigator 
      initialRouteName="WelcomeScreen"
      drawerPosition={"left"}
      drawerStyle={{
      ...
      </Drawer.Navigator>

Of course, being a wise and well written engineer, you create more navigators to stack into you left drawer, and grant them unique headers and bottom tab navigators. Everything is sorted out in a logical fashion. But you are not so familiar with the syntax, so you drop in another NavigationContainer, and make it independent because why not?

const WelcomeNavigatorStack = createBottomTabNavigator<WelcomeParamList>();

export default function BottomTabNavigator() {
  const colorScheme = useColorScheme();

  return (
    <NavigationContainer independent={true}>
    <WelcomeNavigatorStack .Navigator
        initialRouteName="WelcomeScreen"
        tabBarOptions={{ 
            activeTintColor: Colors[colorScheme].tint,
            activeBackgroundColor: 'Blue'
            inactiveBackgroundColor: 'Red'
            labelStyle: {color: 'White'}
        }}>
        <WelcomeNavigatorStack.Screen
            name="WelcomeScreen"
            component={WelcomeScreenComponenets}
            options={{
                tabBarIcon: ({ color }) => <TabBarIcon name="md-rocket" color={'White'} />,
        }}/>  
        <WelcomeNavigatorStack.Screen
            name="LogInScreen"
            component={LogInScreenComponenets}
            options={{
                tabBarIcon: ({ color }) => <TabBarIcon name="md-american-football" color={'White} />,
        }}/> 
    </WelcomeNavigatorStack.Navigator>
    </NavigationContainer>
  );
}

What you dont know is that, by making too many of your tab navigators independent, you have isolated yourself from the parent navigators. So, when you navigate from one isolated tab or stack navigation to the next, you get an error where react has no clue where to go.

The action 'GO_BACK' was not handled by any navigator.

This error persists even when you override the back button. You can test it with alert, and it will work, but when you try to navigation.navigate(), it fails:

useEffect(() => {
        BackHandler.addEventListener('hardwareBackPress', () => {alert('Hello'); return(true)})
        return () => {
            BackHandler.removeEventListener('hardwareBackPress', () => {return(true)})
        }
    }, [])

vs

useEffect(() => {
        BackHandler.addEventListener('hardwareBackPress', () => {navigation.navigate('WelcomeScreen'); return(true)})
        return () => {
            BackHandler.removeEventListener('hardwareBackPress', () => {return(true)})
        }
    }, [])

You may feel tempted to throw your computer out the window, but resist this temptation my friend! Instead, remove your navigation container that wraps your child navigators. By removing the containers that granted these different navigators independence, you can use the hardware back button as intended.

    <WelcomeNavigatorStack .Navigator
        initialRouteName="WelcomeScreen"
        tabBarOptions={{ 
            activeTintColor: Colors[colorScheme].tint,
            activeBackgroundColor: 'Blue'
            inactiveBackgroundColor: 'Red'
            labelStyle: {color: 'White'}
        }}>
        <WelcomeNavigatorStack.Screen
            name="WelcomeScreen"
            component={WelcomeScreenComponenets}
            options={{
                tabBarIcon: ({ color }) => <TabBarIcon name="md-rocket" color={'White'} />,
        }}/>  
        <WelcomeNavigatorStack.Screen
            name="LogInScreen"
            component={LogInScreenComponenets}
            options={{
                tabBarIcon: ({ color }) => <TabBarIcon name="md-american-football" color={'White} />,
        }}/> 
    </WelcomeNavigatorStack.Navigator>

So please, check your code for errant Navigation Containers that are isolating your navigations.

@huynq-tp
Copy link

huynq-tp commented Apr 9, 2021

In react-navigation v5 you can use it's name "cangoback" and you should replace or reset screen

goBack = () => {
    const navigation = this.props.navigation;
    let canGoBack = navigation.canGoBack();
    return canGoBack ? navigation.goBack() : navigation.replace('MainHome');
};

Good Luck!

@calz10
Copy link

calz10 commented May 3, 2021

hi guys. would ask if you guys have resolved this problem already? im on v5 and still experiencing this issue. navigating to another tabnavigator stack screen and call goback method still goes to its parent or inital screen of navigator and not on source of navigation. which is another tab stack screen. thank you. 🙏

@miladr0
Copy link

miladr0 commented May 7, 2021

@calz10 you can do this:

- Dashboard Stack Navigator
   - A

- Accounts Stack Navigator
   - B

when you want to open A screen from B that are in different stacks, pass something like this:

navigation.navigate('A', {initBy:'B'})

now when you are in screen A and you hit back button, do this check:

  const goBack = () => {
    if (initBy) {
      navigation.goBack()
      navigation.navigate(initBy)
    } else {
      return navigation.goBack()
    }
  }

@mrvirus9898
Copy link

mrvirus9898 commented May 16, 2021

hi guys. would ask if you guys have resolved this problem already? im on v5 and still experiencing this issue. navigating to another tabnavigator stack screen and call goback method still goes to its parent or inital screen of navigator and not on source of navigation. which is another tab stack screen. thank you. 🙏

Pass the navigator of the parent screen to the child screens. It is just like passing other objects, or functions to components. So people may scoff at this solution, but its works:

  1. Get navigation object that you want, close to the root screens of your code
  2. Pass this object to the next screens you want to use that object on. DONT JUST NAME IT "NAVIGATION" OR YOU WILL GET CONFUSED
  3. Use navigation object as you will.

From the first navigation body

function BottomTabNavigatorComponentOne({ navigation })
{
    return (
        <SomeDopeComponent
             BottomTabNavigation={navigation}
             SomePropYouNeed={DataThatYouNeed} />)
}

Then later in the code, if your component

function SomeDopeComponent(props: any){
       return(
           <Pressable
                onPress={() => props.BottomTabNavigation.goBack()} >
                <Text>GO BACK TO OTHER NAVIGATION</Text>
           <Pressable />)
}

Just pass the navigation from the screens and components from above the tree, down into the components that you need to use them. Just like passing data along from component to component. Easy as.

@MishaChernov
Copy link

Any solution here?

@github-actions
Copy link

Hey! This issue is closed and isn't watched by the core team. You are welcome to discuss the issue with others in this thread, but if you think this issue is still valid and needs to be tracked, please open a new issue with a repro.

@GreatAuk
Copy link

Any solution here?

image

@felire
Copy link

felire commented Jun 28, 2021

If I am on an ested Stack Navigator and I want to go to the parent navigator and close the state of the nested one. I did:
navigation.popToPop() and then navigation.goBack(). I have to use both of them on that order, I don't know if it is a good solution but it worked to my needs

@armenavanesi
Copy link

Have the exact same problem - any way to achieve this in v6?

@chandansingh01
Copy link

My solution was to create a separate object of the navigation that are used and spread to every stack we need. Something like below.
SharedComponents.js

export default {
    LocationSearchComponent: LocationSearchComponent,
    AddAddress: AddAddress,
    AddFamilyMemberScreen: AddFamilyMember,
    AuthorizeFamilyMember,
    AuthorMemberviaOTP: AuthorizeFamilyMemberViaOtp,
};

import SharedComponents from '@/navigation/Stack/SharedComponents';
const MyCareStack = createStackNavigator(
    {
        MyCareLanding: MyCareLanding,
        PatientTreatmentList: PatientTreatmentList,
        PatientTreatmentDetails: PatientTreatmentDetails,
        ...SharedComponents,
    },
    {
        defaultNavigationOptions: {
            headerShown: false,
        },
    },
);```

This would solve the most navigation issues , because all the components are in the same stack.

@iammeetpatel
Copy link

Is this issue still persist?
Because we are using the below versions, still we can replicate the issue.

"@react-navigation/bottom-tabs": "6.2.0",
"@react-navigation/material-bottom-tabs": "^6.1.1",
"@react-navigation/native": "6.0.8",
"@react-navigation/native-stack": "6.5.2",

@zabojad
Copy link

zabojad commented Aug 2, 2022

I do not see how we could use a single stack when have a bottom tabs navigator...

@wishgoods
Copy link

I have this issue in the same stack when I navigate back I go to home page instead of 1 screen back.
it actually works fine after I refresh the browser.
then it goes 1 screen back.
in android it always works wrong.
I'm wondering if anyone is facing this issue.

@kickbk
Copy link

kickbk commented Feb 10, 2023

Same issue. I'm on a screen in a stack inside a navigator. I navigate to another screen in another stack. The back button goes back to the root of the stack of the screen I navigate to and not to the screen I navigated away from.

@zetziggu
Copy link

same here, on Android:

  • navigate from a departure stack to a modal of an arrival stack
  • the back button leads back to the the departure stack as expected
  • however, upon checking the arrival stack, the modal previously visited is still displayed and there is no way of hiding it i.e. the "cancel" button holding onPress={() => navigation.goBack()} doesn't work

@jeff-jacobsen
Copy link

jeff-jacobsen commented Mar 16, 2023

I do not see how we could use a single stack when have a bottom tabs navigator...

Yeah I don't get why this issue is closed when the documentation for tab navigator goes over this exact scenario. Its pretty normal to want your back behavior to go chronologically across tabs.

@wishgoods
Copy link

wishgoods commented Apr 16, 2023 via email

@zeusstl
Copy link

zeusstl commented May 8, 2023

This is such a basic case - click back to go back to the previous screen that you just came from. How on earth is this not basic behavior? How is react-navigation so popular and can't handle this most basic of cases?

I'm absolutely baffled. I don't even understand what the intended behavior is meant to be. This is navigation - why would you want to navigate back to anything other than the last page you just saw. Everything else should be custom/corner cases.

There is a reason that this ticket is 3+ years of active discussion. Everyone is asking technical questions and trying to hack this to work like any sane navigation would. The discussion needs to switch to "what on earth is the purpose of the current behavior?" This is a super powerful tool that is lacking the most basic feature that any navigation package needs to perform - click go back to go back to the previous page you came from.

@Revolt9k
Copy link

Totally agreed with the previous orator. All of the users expecting that goBack will lead to PREVIOUS screen, no matter from what stack it was be!

@signal451
Copy link

signal451 commented Jun 11, 2023

There is a reason that this ticket is 3+ years of active discussion. Everyone is asking technical questions and trying to hack this to work like any sane navigation would.

I was also wondering same thing here. It's been a 3+ years and they didn't make a progress on this issue

@jaaywags
Copy link

Some of the solutions are nice by saying create a custom back button and handle it using some custom logic. But even if you do this and maintain the users movements in a redux array, there isn't really a way to capture or intercept navigating back using a hardware button or edge swiping, resulting in inconsistent behavior. Maybe android, but on iOS the BackHandler doesn't trigger until after navigating back completes.

@wishgoods
Copy link

wishgoods commented Jun 18, 2023 via email

@lortschi
Copy link

lortschi commented Jun 28, 2023

My setup was the following:

< Container >
  < Stack >
     < Stack.Screen name="Intro" /> <!-- start screen -->
     < Stack.Screen name="Router" /> <!-- inside the Router Component is a nested navigation container with Tab.Screens -->
  </ Stack >
< /Container >

I wasn't able to navigate back from Router Stack to Intro Stack. The error I got on all navigation -> actions was:

"The action 'POP, PUSH etc.' with payload {"name":"Intro","params":{"name":"Intro"}} was not handled by any navigator.

Do you have a screen named 'Intro'?

If you're trying to navigate to a screen in a nested navigator, see https://reactnavigation.org/docs/nesting-navigators#navigating-to-a-screen-in-a-nested-navigator."

How I see the issue (bug) is reagrding of losing context between nested navigation containers. So the child container doesn't know about the parent.

After 1 day of try and error I saw the only possible way would be to use a ref on the parent navigation container and export (forward) the current object as a function. This could be then where ever reused and fire on a navigation action, like e.q. goBack().

Example:

import { createRef } from "react"

export const navigationRef = createRef()

/* as goBack() fn */
export function goBack() {
    navigationRef?.current?.goBack()
}

<NavigationContainer
    ref={navigationRef}
>
   <Stack.Navigator>
	<Stack.Screen
		options={{ headerShown: false }}
		name="Intro"
		component={Intro}
	/>
	<Stack.Screen name="Home" children={() => <Router />} />
   </Stack.Navigator>
</NavigationContainer>


@khanakia
Copy link

khanakia commented Jul 6, 2023

Why we could not solve this issue in all these years? It's so tiring to workaround with custom logic

@OGreeni
Copy link

OGreeni commented Jul 22, 2023

Still waiting for a proper solution... :(

@moshowsJournal
Copy link

moshowsJournal commented Oct 2, 2023

This solution seems to work for me:

  • While resetting the navigator, you need to start from the parent navigator down to the name of the child navigator.

For Instance :

...
<Stack.Screen  name={Main} component={MainStackNavigator} />
...

const MainStackNavigator = () => {
 ....

 <Tab.Screen name="Home" component={HomeStackNavigator} />
  <Tab.Screen name="Wallet" component={WalletStackNavigator} />
....
}

To navigate to screen inside Wallet and still keep the previous stack in history, I do this :

navigation.dispatch(
        CommonActions.reset({
          routes: [
            {
              name: 'Main',
              state: {
                routes: [
                  {
                    name: 'Home',
                    state: {
                      routes: [
                        {
                          name: 'Settings',
                          state: {
                            routes: [{name: 'MyWallet'}],
                          },
                        },
                      ],
                    },
                  },
                ],
              },
            },
            {
              name: 'Main',
              state: {
                routes: [
                  {
                    name: 'Wallet',
                    state: {
                      routes: [
                        {
                          name: 'Deposit',
                        },
                      ],
                    },
                  },
                ],
              },
            },
          ],
        }),
      );

@LuisFelipePereiraDaSilva

Is there already a solution for this case?

@alainib
Copy link

alainib commented Apr 11, 2024

for some people backBehavior props of tabNavigator could solve this problem

https://reactnavigation.org/docs/bottom-tab-navigator/

@KManiKumarReddy
Copy link

The issue is closed? We're still facing the same problem

@Kakaranara
Copy link

Is there still no solution?

@Terence440
Copy link

Terence440 commented May 13, 2024

For my situation & solution:

Navigation Flow:
Screen A: The root screen of your application.
Stack B: A nested stack navigator accessed from "A".
Screen B: The initial screen of "Stack B".
Screen C: Another screen within "Stack B", accessible from "B".

Desired Navigation:
A → B → C: Smooth navigation from "A" to "B" to "C".
C → B: Smooth navigation back from "C" to "B" using navigation.goBack().
B → A: Smooth navigation back from "B" to "A". This is where the problem arises with a simple navigation.goBack().
A → B: Smooth navigation back to "B" from "A".

Problem:
Attempting navigation.goBack() from "B" will not lead back to "A" because it only navigates within "Stack B." Since "B" is the initial screen, there's no previous screen to go back to within the stack.

Solution:

  1. Get Navigation State: Retrieve the current navigation state using navigation.getState().

  2. Identify Current Screen
    const state = navigation.getState(); const currentScreen = state.routes[state.index].state?.routes[ state.routes[state.index].state.index ]?.name;

  3. Conditional Navigation: Based on the identified screen, navigate accordingly:
    if (currentScreen === "B") { navigation.navigate("A"); // Navigate to the root screen } else { navigation.goBack(); // Handle back navigation within "Stack B" }

With this it solves my situation. Hope it helps someone!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests