react-native - 何时从 Authentication SwitchNavigator 导航?
问题描述
我正在我的 React Native 应用程序中设置身份验证流程,我几乎可以让一切正常工作,除了我无法确定使用this.props.navigation.navigate("Main");
.
我的应用程序顶部有一个 Switch Navigator,它呈现身份验证堆栈(它自己的开关导航)和主堆栈:
// App.js
const AppContainer = createAppContainer(
createSwitchNavigator({
Auth: AuthNavigator,
Main: MainTabNavigator,
})
);
export default class App extends Component {
render() {
return (
<Provider store={store}>
<View style={styles.container}>
<AppContainer />
</View>
</Provider>
);
}
}
登录屏幕现在是一个完整的虚拟设置(它调用本地 api 并且无论如何都会成功)。请注意render 方法开始处的条件:
// LoginView.js
class LoginView extends Component {
state = { username: "", password: "" };
handleLogin() {
this.props.login.call(this);
}
render() {
if (this.props.user) {
this.props.navigation.navigate("Main");
return null;
}
return (
<View style={styles.container}>
<Overlay>
<View style={styles.modalContainer}>
<DotIndicator color={"darkgrey"} />
<Text>Logging in...</Text>
</View>
</Overlay>
// ... input components ...
<Button
title="Login"
onPress={this.handleLogin.bind(this)}
/>
</View>
);
}
}
export default connect(
state => ({
isLoading: state.auth.isLoading,
user: state.auth.user,
error: state.auth.error
}),
{ login }
)(LoginView);
现在,这在技术上有效,但我得到了错误Warning: Cannot update during an existing state transition (such as within
render ). Render methods should be a pure function of props and state.
。
我知道这是被抛出的,因为我正在navigate
调用render
. 说得通。
我尝试从我的登录操作导航:
export function login() {
return dispatch => {
dispatch({ type: "LOGIN_START" });
fetch(url) // this will need to be a POST session (not a GET user)
.then(res => res.json())
.then(users => {
dispatch({ type: "LOGIN_SUCCESS", payload: users[0] });
console.log("Login succeeded");
this.props.navigation.navigate("Main");
})
.catch(error => {
console.warn("login failed");
dispatch({ type: "LOGIN_FAILURE", payload: error });
});
};
}
它可以工作,但在关注点分离方面当然是非常错误的,当我尝试使用它来处理登录失败时,这种解决方案也并没有真正延伸。
我也考虑过在我的handleLogin()
函数(由我的登录按钮调用)中执行它,有和没有 async/await:
async handleLogin() {
await this.props.login.call(this);
console.log("Navigating to main screen");
this.props.navigation.navigate("Main");
}
但是导航发生在操作完成并且用户登录之前,一旦认证流程是真实的,这当然是不可接受的。(另外,当我使用 async/await 执行此操作时,“登录成功”会被记录两次!击败我)。确实感觉我在我的handleLogin()
职能中走在正确的轨道上。
我在哪里navigate
打电话?
解决方案
我似乎找到了一些可行的方法,但它与 Redux 相去甚远,这让我有点不舒服。
我已经从 Redux 操作中提取了所有内容,并将其放入我的LoginView
. 我在 Redux 术语中认为这没问题,因为程序需要了解授权过程和状态的唯一地方是授权流程本身(目前就其LoginView
本身而言)。商店和应用程序的其余部分唯一需要知道的是用户的信息。
所以我login
用一个简单的动作替换了我的 ReduxassignUser
动作。在发布状态更改以激活我的“登录...”覆盖后,我已经将获取重构为performLogin
从旧调用的 fetching。handleLogin
// authActions.js
export function assignUser(user) {
return dispatch => {
console.log("user", user);
dispatch({ type: "LOGIN_SUCCESS", payload: user });
};
}
// from LoginView.js
performLogin() {
fetch("http://127.0.0.1:3000/users") // this will need to be a POST session (not a GET user)
.then(res => res.json())
.then(users => {
console.log("Login succeeded");
this.props.assignUser(users[0]);
console.log("Navigating to main screen");
this.props.navigation.navigate("Main");
})
.catch(error => {
console.warn("login failed", error);
this.setState({isLoading: false})
});
}
handleLogin() {
this.setState({ isLoading: true }, this.performLogin);
}
组件的其余部分LoginView
与我原来的帖子中的相同。
我仍然很想知道是否有人有任何方法可以完成此操作,从而将操作完全保留在 Redux 中。
推荐阅读
- android - 警报管理器和广播接收器不会长期触发
- node.js - Mongo:将($l0okup)集合加入一个大文档
- c++ - g++:错误:第一:没有这样的文件或目录(在 VScode 2021 上运行 c++)
- javascript - javascript和html中的确认对话框
- jsf - 如何切换没有类的组件内所有输入的禁用状态?
- google-cloud-platform - 无法编辑 GCP 负载平衡器
- reactjs - 使用 React 的 Electron - 渲染大量项目会导致 CPU 使用率高
- python - 如何避免多次调用 pytest_generate_tests
- database - 任何浏览器内的方式来运行 MongoDB 的查询,比如 pgweb 对 postgres/heroku 有什么作用?
- microsoft-graph-api - 在 ms 图中上传大于 4mb 的 xlsx 文件 powershell 失败