React navigation to navigate from redux action file
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);
Subrata Mallik
Updated on June 26, 2022Comments
-
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 over 5 yearsTake a look to the documentation, they really advise to not do this. Be careful.
-
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 almost 5 yearswhat is "TopLevelNavigator" where is it coming from in App.js? -1 for no guidence..
-
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 almost 4 yearsHow 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 over 3 yearsCan you explain what is TopLevelNavigator ? I don't understand your solution