3
votes

I'm new to RN and JS.

I want to navigate once a login action is complete, but I cannot get it to work. I am using firebase.

This is from my actions file. It throws a firebase error:

export const LOGIN_USER_SUCCESS = 'login_user_success';
export const loginUserSuccess = (dispatch, user) => {
  dispatch({
    type: LOGIN_USER_SUCCESS,
    payload: user
  });
    this.props.navigation.navigate('groupMain');     // this doesnt work
};

I also tried putting it into the Login component - this might be a step in right direction because there is no firebase error, but nothing happens. So it seems that all works, except the user is not navigated to the proper screen. (I removed the 'this doesnt work' line from above)

componentWillReceiveProps(nextProps) {
    this.onAuthComplete(nextProps);
  }

  onAuthComplete(props) {
    if (props.user) {
      this.props.navigation.navigate('groupMain');
    }
  }

Later, I also found this in the official docs and tried to implement by using this code in my action, but it threw a firebase error:

"dispatch - Send an action to the router

Use dispatch to send any navigation action to the router. The other navigation functions use dispatch behind the scenes.

Note that if you want to dispatch react-navigation actions you should use the action creators provided in this library.

See Navigation Actions Docs for a full list of available actions.

import { NavigationActions } from 'react-navigation'

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

  // navigate can have a nested navigate action that will be run inside the child router
  action: NavigationActions.navigate({ routeName: 'SubProfileRoute'})
})
this.props.navigation.dispatch(navigateAction)"

thanks!

1

1 Answers

4
votes

I solved a similar problem by creating a global service to handle programmatic navigation:

services/navigator.js

import { NavigationActions } from 'react-navigation';

let navigator;

export function setNavigator(nav) {
   navigator = nav;
}

export function navigate(routeName, params) {
   if (navigator) { 
      navigator.dispatch(NavigationActions.navigate({routeName, params}));
   }
}

export function goBack() { ... }

export function reset() { ... }

Then, in my top-level component I store the reference to the navigator when it's created:

screens/App.js

import { setNavigator } from '../services/navigator';

const AppNavigator = StackNavigator(...);

class App extends Component {
   render() {
      return (
         <AppNavigator ref={nav => setNavigator(nav)} />
      );
   }
}

And finally in my action files (or wherever I need to), I simply use the service to dispatch navigation actions:

actions/login.js

import { navigate } from '../services/navigator';

export function loginUserSuccess() {
   // use navigate() anywhere you'd normally use this.props.navigation.navigate()
   navigate('NextScreen');
}