Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

pass parameters between two stacks - React Native

my app should have a login screen, with Google, so when signed in it goes to the menu screen.

in order to not go back to the login screen when pressing the back button, after getting to the menu screen after the authentication. I've separated the stacks one for the login and one for the other screens

in App.js:

const AuthStack = createStackNavigator({
  LoginSplashScreen: LoginSplashScreen 
});
const AppStack = createStackNavigator({ 
  MenuScreen:MenuScreen,
  DetailsScreen: DetailsScreen,
  PhotoScreen: PhotoScreen,
  DocumentScreen: DocumentScreen,
  AudioScreen: AudioScreen,
  ScheduleScreen: ScheduleScreen,
  SettingsScreen: SettingsScreen,
  FilesScreen: FilesScreen,
  GalleryScreen: GalleryScreen
   });


const Root= createAppContainer(createSwitchNavigator(
  {
    AuthStack:AuthStack,
    AppStack:AppStack
  },
  {
    initialRouteName: 'AuthStack',
  }
));

export default class App extends React.Component {
  render() {
    return (
      <Root/>  
    )
  }
}

so in the LoginSplashScreen after authenticating I used this code to navigate:

    this.props.navigation.navigate('AppStack', {
      signedIn: true,
      name: result.user.name,
      photoUrl: result.user.photoUrl
    });

the navigation works great, but the parameters 'name','signedIn','photoUrl' do not pass in fact, when alerting

    Alert.alert('',JSON.stringify(this.props.navigation.state.params))

on the menu screen(second stack), it is empty

what am I doing wrong?

why my parameters aren't passing? because I might need another drawer navigation .

is there a way to set global parameters for all screens in the application?

Is there a better way to avoid pressing back on menu Screen and not getting the login screen?

EDIT:

I managed to solve this specific problem with setting a global parameter with:

global.param= result.param;

but, I still need an answer for passing between 2 separated stacks

like image 229
Dor Lugasi-Gal Avatar asked Dec 29 '18 16:12

Dor Lugasi-Gal


1 Answers

By creating two separate stacks, you have sort of detached the params scope, what you are trying to do is: sending params using a different navigation scope to a completely different navigation scope which actually is completely unaware of the previous one although living in a common parent.

When you are using this.props.navigation from LoginSplashScreen you are actually in a sandboxed navigation scope of your AuthStack which is confined to its own navigator's routes. Now when you are binding both of your stacks in a single navigator as Routes of the SwitchNavigator, you are entering in a parent navigator's scope which gives its own navigation prop, so if you would have used the navigation prop of the switch navigator, then you would have got the params in your AppStack but since.

What I would suggest are the below three ways for correctly doing it:

  1. Using Login Screen as a direct route for the SwitchNavigator thereby removing the useless stack navigator for login which is detaching the routing.

The code should look like:

const Root= createAppContainer(createSwitchNavigator({
   LoginSplashScreen: LoginSplashScreen 
   AppStack:AppStack
}, {
initialRouteName: 'LoginSplashScreen',
}));
  1. Using redux to store data in a commonly accessible store and using it on the different components as described in the other answer, but this is not a reason for using redux primarily.

  2. Using a New Component in place of AppStack in the switch navigator while having LoginSplashScreen as one of the direct routes of SwitchNavigator and rendering AppStack inside of the New Component and passing the received params as screenProps in the AppStack then simply using the screenProps in the stack routes.

The code should look like:

 const Root= createAppContainer(createSwitchNavigator({
   LoginSplashScreen: LoginSplashScreen, 
   MyMediatorScreen: MyFancyComponent
}, {
initialRouteName: 'AuthStack',
}));

For eg. the FancyComponent will be like the below:

class MyFancyComponent extends React.Component{
   constructor (props){
      super (props); 
   }

   render () {
     const {params} = this.props.navigation.state;
     return (
        <AppStack screenProps = {params} />
     )
   }
}
like image 93
Suraj Malviya Avatar answered Nov 07 '22 18:11

Suraj Malviya