React navigation to navigate from redux action file

15,177

Solution 1

EDIT: 9 Aug 2018

After the major rewrite of react-navigation, integrating with Redux is discouraged. There are, however, new tools to allow you to control navigation from anywhere. See, for example, how to create a NavigationService that provides this functionality

No Longer Valid - Don't do this

You haven't specified whether your navigation state is held in Redux, so if not, you should definitely integrate react-navigation and Redux.

The react-navigation documentation on how to do it is pretty clear.

After that, navigating becomes just another dispatch, only the actions come from react-navigation:

dispatch(NavigationActions.navigate({
  routeName: 'dashboard',
}));

Solution 2

import firebase from 'firebase';
import { NavigationActions } from 'react-navigation';


// Login actions
export const LoginAction = (payload) => {
  return (dispatch) => {
    firebase.auth().signInWithEmailAndPassword(payload.email, payload.password)
      .then(user => loginSuccess(dispatch, user))
      .catch((error) => {
    loginFail(dispatch, error);
    });
  };
};

// Login success function

logoutSuccess = (dispatch, user) => {
  // dispatch an action
  dispatch({
    type: 'LOGOUT_SUCCESS',
    payload: user
  });  
  const navigateAction = NavigationActions.navigate({
      routeName: "dashboard",
      params: {},
      action: NavigationActions.navigate({ routeName: "dashboard" })
    });
  this.props.navigation.dispatch(navigateAction); // this is where you use navigation prop
};

// add this nav reducer to your root reducer

import Root from 'your navigation root path';

const navReducer = (state, action) => {
  const newState = Root.router.getStateForAction(action, state)
  return newState || state
}

export default navReducer;

Solution 3

Solution for v2 in 2018:

1) Define a NavigationService.js file

import { NavigationActions } from 'react-navigation';

let navigator;

 function setTopLevelNavigator(navigatorRef) {
  navigator = navigatorRef;
}

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


 export default {
  navigate,
  setTopLevelNavigator,
 };

2) Inside App.js you should have something like this: (redux provider, the store and the top level navigator set up before)

import AppNavigation from 'route-to-NavigationService';

<Provider store={store}>
    <TopLevelNavigator
      ref={(navigatorRef) => {
      NavigationService.setTopLevelNavigator(navigatorRef);
      }}
    />
</Provider>

3) Inside from your action: import NavigationService from 'route-to-NavigationService';

function logIn(){
     //async code
     ...
     dispatch(() => {
          NavigationService.navigate('RouteNameToNav'),
     });
}

Extra: If you want to reset your navigation stack (i.e Login should reset navigation stack), then inside your dispatch, your should do:

  dispatch(() => {
      StackActions.reset({
        index: 0,
        actions: [NavigationService.navigate('App')],
      });
    });

Solution 4

I have a quik and easy solution:

In the case where you have to navigate to specific screen, you can pass the navigation as a param to your redux action creator function

Example of lougout action:

Redux action:

export function handleLogout(navigation) {
    return (dispatch) => {
        dispatch(handleLoggingOut(true));
        setTimeout(() => {
            STORAGE.removeData('@FunnyLive:token').then(() => {
                dispatch(handleLoggingOut(false));
                navigation.navigate({routeName: 'Auth'});
            })
        }, 2000);
    }
}

mapDispatchToProps:

const mapDispatchToProps = (dispatch) => ({
  logout: (navigation) => dispatch(handleLogout(navigation))
})

Finally you have to call the action like this:

() => this.props.logout(this.props.navigation);
Share:
15,177
Subrata Mallik
Author by

Subrata Mallik

Updated on June 26, 2022

Comments

  • Subrata Mallik
    Subrata Mallik almost 2 years

    I want to navigate from my reduc action file. 1st screen is login so after click on login button will call a redux action creator and reducer generate a new state. So, after the action i want to rediret to my dashboard.

    I am using

    react native + redux + react navigation

    Login component file (LoginCmp.js):

    import React, { Component } from 'react';
    import {
      Text,
      View,
      ScrollView,
      KeyboardAvoidingView
    } from 'react-native';
    import { connect } from 'react-redux';
    import { fieldChange, LoginAction } from '../../actions';
    import { Button, Section, Input, Alert } from '../Helpers';
    
    LoginAction(){
      const payload = {
        email: this.props.email,
        password: this.props.password
      };
      this.props.LoginAction(payload); // Action call
    }
    
    
    render() {
        return (
          <KeyboardAvoidingView
        style={styles.container}
        behavior="padding"
          >
          <View>
        <ScrollView contentContainerStyle={styles.contentContainer}>
          <Text style={styles.headerText}> Login </Text>
          {this.alertMessage()}
          <Section>
            <Input
              placeholder="[email protected]"
              onChangeText={this.onFieldChange.bind(this, { actionType: 'EMAIL_CHANGED' })}
              value={this.props.email}
            />
          </Section>
          <Section>
            <Input
              secureTextEntry
              placeholder="Password"
              onChangeText={this.onFieldChange.bind(this, { actionType: 'PASSWORD_CHANGED' })}
              value={this.props.password}
            />
          </Section>
          <Section>
            <Button
              onPress={this.LoginAction.bind(this)}
              style={styles.buttonLogin}
            >
              Submit
            </Button>
          </Section>
        </ScrollView>
          </View>
          </KeyboardAvoidingView>
        );
      }
    }
    
    const mapStateToProps = ({ auth }) => {
      console.log(auth);
      return auth;
    };
    
    export default connect(mapStateToProps, { fieldChange, LoginAction })(LoginCmp);
    

    Router file (Router.js):

    const RouterComponent = StackNavigator({
      login: { screen: LoginCmp },
      dashboard: { screen: DashboardCmp },
    });
    

    Action creator file (AuthActions.js):

    import firebase from 'firebase';
    import { NavigationActions } from 'react-navigation';
    
    
    // Login actions
    export const LoginAction = (payload) => {
      return (dispatch) => {
        firebase.auth().signInWithEmailAndPassword(payload.email, payload.password)
          .then(user => loginSuccess(dispatch, user))
          .catch((error) => {
        loginFail(dispatch, error);
        });
      };
    };
    
    // Login success function
    
    logoutSuccess = (dispatch, user) => {
    // dispatch an action
    dispatch({
      type: 'LOGOUT_SUCCESS',
      payload: user
    });  
    ### From here i want to navigate to dashboard.
    };
    
  • Vincent Decaux
    Vincent Decaux over 5 years
    Take a look to the documentation, they really advise to not do this. Be careful.
  • Kraylog
    Kraylog over 5 years
    @VincentDecaux At the time of writing this answer, Redux integration was part of the documentation. Since then, they have altered their approach, and it is now indeed inadvisable.
  • TyForHelpDude
    TyForHelpDude almost 5 years
    what is "TopLevelNavigator" where is it coming from in App.js? -1 for no guidence..
  • Emmanuel Orozco
    Emmanuel Orozco almost 5 years
    @TyForHelpDude As the name implies, it is the main navigator of your app. Usually is defined in your project set up.
  • sejn
    sejn almost 4 years
    How can I pass an array of object from one to another screen while dispatch also how can I get that in the next screen Ex) dispatch(NavigationActions.navigate({ routeName: 'SettingsScreen', params: {id}}));
  • saperlipopette
    saperlipopette over 3 years
    Can you explain what is TopLevelNavigator ? I don't understand your solution