Reputation: 97
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.
};
Upvotes: 5
Views: 22765
Reputation: 84
As described in react-navigation v6 docs. You can use the react-navigation functions from outside the react components.
// RootNavigation.js
import { createNavigationContainerRef } from '@react-navigation/native';
export const navigationRef = createNavigationContainerRef()
export function navigate(name, params) {
if (navigationRef.isReady()) {
navigationRef.navigate(name, params);
}
}
// add other navigation functions that you need and export them
Navigate without the navigation props from docs for react-navigation v5
Upvotes: 0
Reputation: 2430
In navigation 5 and Redux
for examle I have component Login
const LoginScreen = (props) => {
return (
<View style={styles.continer}>
<Login navigation={props.navigation}/>
</View>
)
}
in component Login i have function login
import { connect} from 'react-redux';
import {userLogin} from './action/userAction';
const login =()=>{
const {username,password, navigation } = props;
userLogin(username,password, navigation )
}
const mapStateToProps = (state) => {
return{
username:state.auth.username,
password:state.auth.password,
}
};
export default connect(mapStateToProps,{userLogin})(Login) ;
and in userAction file
export const userLogin = (username, password, navigation) => {
return dispatch => {
// .... any code
loginSucess(dispatch, navigation)
}
}
const loginSucess = (dispatch, navigation) => {
dispatch({
type: USER_LOGIN_SUCSESS,
})
navigation.replace("Home")
}
Upvotes: 0
Reputation: 1700
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);
Upvotes: 2
Reputation: 7553
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
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',
}));
Upvotes: 9
Reputation: 497
one hacky way that worked for me is that you can send navigation prop to your action
<Button rounded block onPress={() => this.props.nav(this.props.navigation)}>
<Text>
nav
</Text>
</Button>
then in your action file:
export function navAction(navigation) {
return (dispatch) => {
navigation.navigate('yourRoute')
}
}
Upvotes: -1
Reputation: 389
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')],
});
});
Upvotes: 2
Reputation: 625
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;
Upvotes: 2