SwimmingG
SwimmingG

Reputation: 664

StackNavigation don't add screen to stack React Native

I have the current flow of screens.

Home -> Info -> Log in -> Camera.

The issue is that I don't want to add Login to the stack because then when you go back from the camera you will go back to login, rather than information.

If I use this.props.navigate('Info') from the camera, then the issue is that back now goes to the camera rather than home from info. Note I also don't want to complete delete the stack at the login page as I've seen with the Reset function here (https://reactnavigation.org/docs/navigators/navigation-actions#Reset).

Ideally what I would like to do would be:

Home -> Info -> Login (Not added to stack) -> Camera.

This was I can just go back from Camera to Info and from Info to Home.

Has anyone found a nice way around this?

Thanks

Upvotes: 0

Views: 1054

Answers (2)

Jack Bridger
Jack Bridger

Reputation: 165

With v6 of Navigation, CommonActions.reset might might work for you:

import { useNavigation,CommonActions } from "@react-navigation/native";
...
const navigation = useNavigation();
...
 navigation.dispatch((state) => {
          // We can keep all routes on the stack except that which has name "Login"
          const routesWithoutLogin = state.routes.filter((r) => r.name !== "Login");

          // We can then define the new route we want
          const routeToAdd = {
            name: "Info",
            params: {},
          };

          const newRoutes = [...routesWithoutLogin, routeToAdd];

          return CommonActions.reset({
            ...state,
            routes: newRoutes,
            index: newRoutes.length - 1,
          });
        });

Reference here: https://reactnavigation.org/docs/navigation-actions/#reset

When debugging, I find it quite useful to log my routes state to see what needs changing.

import { useNavigation,CommonActions } from "@react-navigation/native";
...
const navigation = useNavigation();
...
console.log(navigation.getState().routes);

It should look something like this

     [{"key": "Root-YhPzpMumgvLs62ZwxjOJW", "name": "Root", "params": undefined}, {"key": "Chat-sDA1-4R0fImaxaj9maXGb", "name": "Chat", "params": {"conversation": [Object]}, "path": undefined}]

One more note, when I tried creating routes from scratch, I lost some of my redux state. It seems like a better idea to filter out routes you don't want than to make them from scratch.

Upvotes: 0

Eduard
Eduard

Reputation: 9205

If you want to retain the whole stack and params, only ditching the Login page, then you could use Reset Navigation Action either in the Camera page :

import { NavigationActions } from 'react-navigation'

const resetAction = NavigationActions.reset({
  index: 1,
  actions: [
    NavigationActions.navigate({ routeName: 'Home', params: this.props.navigation.state.params })
    NavigationActions.navigate({ routeName: 'Info', params: this.props.navigation.state.params })
  ]
})
this.props.navigation.dispatch(resetAction)

This way you will:

  1. Navigate to Info page on top of Home page, meaning that Back button will lead to Home page.
  2. Retain the params, if you need. If you don't just do not pass them.

This functionality could be added anywhere: inside the components / inside the Action Creators / inside the Back button.

Or add the same code for the Back button. In this case you need to add this to the navigationOptions of Camera route:

const backButton = ({ navigation }) => ({
        headerLeft: <TouchableOpacity
                    onPress={() => {
                    // the code from above, except for import line and using navigation.whatever instead of this.props.navigation.whatever
                    }}
                ><Text>Back</Text> // this is a text of a back button, you could also use an icon
                </TouchableOpacity>
});

Navigator:

const MyStack = StackNavigator({
  home: { screen: Home },
  info: { screen: Info },
  login: { screen: Login },
  camera: { screen: Camera }, navigationOptions: backButton });

Upvotes: 1

Related Questions