26

I am trying to get previous route name to my current screen. Because based on the previous screen name, I have to show/hide few objects in current screen.

To get previous screen name, I have tried following

componentDidMount() {
    const { navigation } = this.props;
    if (navigation.state.params && navigation.state.params.previous_screen) {
       console.log('navigation.state.params.previous_screen', navigation.state.params.previous_screen);
    }
}

But, It's getting undefined in console log.

Any suggestions?

Derek Pollard
  • 6,953
  • 6
  • 39
  • 59

8 Answers8

21

For Stack Navigators, I was able to dynamically get the previous route name in react-navigation v6 with:

// `navigation` const is passed to the screen component or from useNavigation()
const routes = navigation.getState()?.routes;
const prevRoute = routes[routes.length - 2]; // -2 because -1 is the current route

Note: This is super useful for dynamically passing params back to a previous screen. Beware of nested routes though, the syntax is slightly different.

if (prevRoute.name === "<Some Routing Key>") {
      navigation.navigate("<Some Routing Key>", params);
}
Conor Lamb
  • 307
  • 2
  • 5
9

You need to use NavigationActions

goToScreen = () => {

  const navigateAction = NavigationActions.navigate({
    routeName: 'Profile',

    params: { previous_screen: 'Home' }, // current screen

    action: NavigationActions.navigate({ routeName: 'Profile' }), // screen you want to navigate to
  });

  this.props.navigation.dispatch(navigateAction);
  
};

call the above function in your onPress

<Text onPress={this.goToScreen}>Go to screen</Text>

In your other screen

componentDidMount = () => {
  
  const { navigation } = this.props;
  if (navigation.state.params && navigation.state.params.previous_screen) {

    this.setState({
      previous_screen: navigation.state.params.previous_screen
    });

  } else {
    console.log("ERROR");
  }
};

Working demo

Function version

const goToScreen = () => {
  // assuming that navigation is passed in props
  props.navigation.navigate('Settings', {
    previous_screen: 'Home'
  })
}

And access the params like

const Settings = ({ route }) => {
  const { previous_screen } = route.params;

  return ....
}
Junius L
  • 15,881
  • 6
  • 52
  • 96
8

I got the proper way to found previous route (screen) name from current screen

 props.navigation.dangerouslyGetParent().state.routes 

You will get the list(array) of screen from navigation stack. example like

Output is here

Array(0) [, …]
0:Object {routeName: "ROUNTE_NAME", key: "id-158*****6785-1"}
1:Object {params: Object, routeName: "Screen1", key: "Screen1"}
2:Object {params: Object, routeName: "Screen2", key: "Screen2"}

Thanks guys - K00L ;)

kuldip bhalodiya
  • 992
  • 7
  • 11
2

Using navigation ref, you can have access to the root state.
This block helps check if the target route is inside a nested navigation/route (currentRoute?.state?.index > -1 && currentRoute?.state?.routes) ? currentRoute?.state?.routes?.[currentRoute?.state?.index]

      const getRecentRoutes = ()=> {
        const rootState = navigationContainerRef.current?.getRootState();
        const routes = rootState?.routes;
        const previousRoute = routes?.[routes?.length - 2];
        const currentRoute = routes?.[routes?.length - 1];
        return {
          currentRoute: (currentRoute?.state?.index > -1 && currentRoute?.state?.routes) ? currentRoute?.state?.routes?.[currentRoute?.state?.index] : currentRoute,
          previousRoute: (previousRoute?.state?.index > -1 && previousRoute?.state?.routes) ? previousRoute?.state?.routes?.[previousRoute?.state?.index] : previousRoute,
        };
      };
Mkay4real
  • 23
  • 5
1

I used the below approach. This may be not the best approach but it does work.

let routes = this.props.navigation.dangerouslyGetState().routes[0].state.history;
for (let idx = routes.length - 1; idx >= 0; idx--) {
  if (routes[idx].type == 'route') {
    let route = routes[idx].key;
    this.props.navigation.navigate(route.substr(0, route.indexOf('-')));
    break;
  }
}
Hp Sharma
  • 309
  • 3
  • 7
0
const navigateAction = NavigationActions.navigate({
  routeName: 'Profile',
  action: NavigationActions.navigate({ routeName: 'Profile', params: { previous_screen: 'Home' } }),
});
this.props.navigation.dispatch(navigateAction);
Esha Singh
  • 19
  • 2
  • 3
  • 9
    You should comment the code you pasted here, how this code will answer OP question? – dbraillon Jan 10 '20 at 08:55
  • 4
    Code only answers are rarely helpful. Please comment your code or expound on why this is the solution to the question. – RyanNerd Jan 10 '20 at 11:41
0

Using react-navigation v5 you can recurse the navigation state using the routes and index to find the current route. Once you have found the current route, an object that doesn't have any child routes, you can subtract 1 from the index to get the previous route.

The code to achieve this looks something like

const getPreviousRouteFromState = (route: NavigationRoute) => {
  let checkRoute = null
  if (route.state && route.state.index > -1 && route.state.routes) {
    checkRoute = route.state.routes[route.state.index]
    if (checkRoute.state && checkRoute.state.routes) {
      return getPreviousRouteFromState(checkRoute)
    }
    const previousRouteIndex = route.state.index - 1
    if (previousRouteIndex > -1) {
      checkRoute = route.state.routes[previousRouteIndex]
    }
  }
  return checkRoute
}

This strategy has some limitations - it will return the current route when navigating back due to limitations of a stack. It also returns the current screen when switching stacks.

Corey
  • 1,010
  • 9
  • 17
  • Where are you using it? The route in a screen component only has a `key`, `name`, and `params` keys. No `state`. – Ryan Pergent Dec 02 '20 at 14:11
  • I'm using it like this `const navState = useNavigationState((state) => state) const prevRoute = getPreviousRouteFromState({ state: navState })` – Corey Dec 02 '20 at 17:44
0

Define some functions in app.js | index.js. Means initial screen

setActiveScreen = (activeScreen) => { 
    const previousScreen = this.state.activeScreen
    this.setState({activeScreen: activeScreen, previousScreen: previousScreen})
  }
  goBackScreen = () => {
    this.setState({activeScreen: this.state.previousScreen});
  }

And pass this functions to the navigation screens

<Stack.Screen >   
{(props) => <ComponentScreen goBackScreen={this.goBackScreen} setActiveScreen={this.setActiveScreen} /> }
</Stack.Screen>

Then run the goBackScreen before you use the navigation.goBack() in screens

<TouchableOpacity onPress={() => {
this.props.goBackScreen()
this.props.navigation.goBack();
}}><Text>Click</Text> </TouchableOpacity>

Note: now you can get the previous screen name in activeScreen. It's just an example for the possibility. And you can try your own idea


Or you can pass the previous screen in params

navigation.navigate("home", {params: {previousScreen: '{{pass the currentScreen name}}'

then the next screen you can get it by console.log(this.props.route.params)

Karthikeyan Ganesan
  • 1,901
  • 20
  • 23