反应导航以从 redux 操作文件导航
Posted
技术标签:
【中文标题】反应导航以从 redux 操作文件导航【英文标题】:React navigation to navigate from redux action file 【发布时间】:2018-06-04 20:59:39 【问题描述】:我想从我的减少操作文件中导航。 第一个屏幕是登录,所以点击登录按钮后会调用一个 redux action creator 和 reducer 生成一个新状态。所以,在操作之后我想重定向到我的仪表板。
我正在使用
react native + redux + react 导航
登录组件文件(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@gmail.com"
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.js):
const RouterComponent = StackNavigator(
login: screen: LoginCmp ,
dashboard: screen: DashboardCmp ,
);
动作创建者文件(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.
;
【问题讨论】:
您必须订阅 redux 状态才能登录并在 redux 操作更改状态值时更改导航。这将是一个正确的方法。 【参考方案1】:编辑:2018 年 8 月 9 日
在对 react-navigation 进行重大重写后,不鼓励与 Redux 集成。但是,有一些新工具可让您从任何地方控制导航。例如,请参阅提供此功能的 how to create a NavigationService
不再有效 - 不要这样做
你还没有指定你的导航状态是否保存在 Redux 中,所以如果没有,你肯定应该集成 react-navigation 和 Redux。
react-navigation documentation on how to do it 非常清晰。
之后,navigating 就变成了另一个 dispatch,只有 action 来自 react-navigation:
dispatch(NavigationActions.navigate(
routeName: 'dashboard',
));
【讨论】:
查看文档,他们真的建议不要这样做。小心。 @VincentDecaux 在撰写此答案时,Redux 集成是文档的一部分。从那以后,他们改变了方法,现在确实不可取。 如何在调度时将对象数组从一个屏幕传递到另一个屏幕,如何在下一个屏幕中获取它 Ex) dispatch(NavigationActions.navigate( routeName: 'SettingsScreen', params: id));【参考方案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
;
// 将此导航减速器添加到您的根减速器
import Root from 'your navigation root path';
const navReducer = (state, action) =>
const newState = Root.router.getStateForAction(action, state)
return newState || state
export default navReducer;
【讨论】:
【参考方案3】:2018 年 v2 解决方案:
1) 定义一个 NavigationService.js 文件
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) 在App.js
内部你应该有这样的东西:(redux 提供者,商店和***导航器之前设置)
import AppNavigation from 'route-to-NavigationService';
<Provider store=store>
<TopLevelNavigator
ref=(navigatorRef) =>
NavigationService.setTopLevelNavigator(navigatorRef);
/>
</Provider>
3) 在你的行动中: 从 'route-to-NavigationService' 导入 NavigationService;
function logIn()
//async code
...
dispatch(() =>
NavigationService.navigate('RouteNameToNav'),
);
额外:如果您想重置导航堆栈(即登录应该重置导航堆栈),那么在您的调度中,您应该这样做:
dispatch(() =>
StackActions.reset(
index: 0,
actions: [NavigationService.navigate('App')],
);
);
【讨论】:
什么是“TopLevelNavigator” 它来自 App.js 中的什么地方? -1 没有指导意义.. @TyForHelpDude 顾名思义,它是您应用的主要导航器。通常在您的项目设置中定义。 你能解释一下什么是 TopLevelNavigator 吗?我不明白你的解决方案【参考方案4】:对我有用的一种 hacky 方式是您可以将导航道具发送到您的操作
<Button rounded block onPress=() => this.props.nav(this.props.navigation)>
<Text>
nav
</Text>
</Button>
然后在您的操作文件中:
export function navAction(navigation)
return (dispatch) =>
navigation.navigate('yourRoute')
【讨论】:
【参考方案5】:我有一个简单快捷的解决方案:
在你必须导航到特定屏幕的情况下,你可以将导航作为参数传递给你的 redux action creator 函数
lougout 动作示例:
Redux 操作:
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))
)
最后你必须像这样调用动作:
() => this.props.logout(this.props.navigation);
【讨论】:
【参考方案6】:在导航 5 和 Redux 中
例如我有组件登录
const LoginScreen = (props) =>
return (
<View style=styles.continer>
<Login navigation=props.navigation/>
</View>
)
在组件登录中我有登录功能
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) ;
在 userAction 文件中
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")
【讨论】:
【参考方案7】:如react-navigation v6 docs 中所述。您可以从反应组件外部使用反应导航功能。
// 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 来自 react-navigation v5 文档
【讨论】:
以上是关于反应导航以从 redux 操作文件导航的主要内容,如果未能解决你的问题,请参考以下文章
dispatchin action redux 后导航与 react native
每次使用反应路由器导航到redux组件时,如何阻止状态存储数据在redux组件中累积