使用 React 本机导航在 dispatch redux 上注销错误
Logout error on dispatch redux with React native navigation
在我的 React Native 应用程序中,实际上我需要使用导航和 redux 实现一个简单的注销,但是当我从主页发送注销操作时出现错误 (按下注销按钮), 因为在 Home 中我呈现当前用户并且在那一刻不存在。
我需要调度注销(删除当前用户)并在导航到登录页面后再次渲染主页或了解如何在渲染之前实现 componentWillMount....
如何?
我的简历代码:
(登录有效,我没有输入登录码)
App.tsx
import React, {useState} from 'react';
import { NavigationContainer, StackActions } from '@react-navigation/native';
//... many imports
const store = createStore(rootReducer);
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = { loading: true };
}
async componentDidMount() {
//... some code
}
render(){
if (this.state.loading) {
return (
<Root>
<AppLoading />
</Root>
);
}
else {
return (
<Provider store={store}>
<Root>
<NavigationContainer>
<Navigator/>
</NavigationContainer>
</Root>
</Provider>
);
}
}
}
Navigator.tsx
import React from 'react'
import { createStackNavigator } from '@react-navigation/stack'
import {connect} from 'react-redux'
import Login from '../Views/Login'
import Home from '../Views/Home'
const Stack = createStackNavigator();
const Navigator= (props) =>{
const {users} = props;
return (
<Stack.Navigator>
{console.log('Navigator here, '+users.current)}
{users.current ===null ?
(<>
<Stack.Screen name="Login" component={Login} options={{headerShown:false}}/>
</>)
: (<>
<Stack.Screen name="Home" component={Home} options={{headerShown:false}}/>
</>)
}
</Stack.Navigator>
);
}
const mapStateToProps=(state)=>{
const {users} = state;
return {users};
}
export default connect(mapStateToProps)(Navigator);
Home.tsx(注销后导航?)
import React from 'react'
import {Text, Container, Content, View, Button, Icon} from 'native-base'
import Styles from './Styles/HomeStyles'
import {connect} from 'react-redux'
import {Auth} from '../Services/Auth/AuthService'
const Home =(props) => {
const {navigation, users} = props;
return(
<Container >
<Content >
<View style={Styles.content}>
<Text>Hi {users.current.id}</Text>
<Button onPress={()=>Logout(users.current.id)} >
<Icon name='exit' />
</Button>
</View>
</Content>
</Container>
);
async function Logout(id:string){
console.log('Function start');
await Auth.LogoutUser(id, props);
navigation.navigate('Login');
}
}
const mapStateToProps=(state)=>{
const {users} = state;
return {users};
}
export default connect(mapStateToProps)(Home);
UserReducer.tsx
const Initial_State={
current:null
}
export function UserReducer(state=Initial_State, action:any){
switch (action.type){
case 'ADD_USER':
return{
...state,
current: action.user
};
case 'DELETE_USER':
return{
...state,
current: null
};
default:
return state;
}
}
AuthService.tsx(这里是dispatch)
export const Auth={
LoginUser,
LogoutUser
}
async function LogoutUser(id: string, props: any){
await props.dispatch({type : 'DELETE_USER', id});
}
async function LoginUser(AuthData:IAuthData, props: any){
//...some code
}
在您的情况下,您现在可以通过更改
来处理 users 变量的空状态
<Text>Hi {users.current.id}</Text>
至
<Text>Hi {users?.current?.id}</Text>
但在实际应用中,您应该必须重置完整的应用状态,并且必须在该应用状态上管理您的条件。
示例:
import { combineReducers } from 'redux';
import UsersReducer from './UsersReducer';
const appReducer = combineReducers({
users: UsersReducer,
// other Reducers if there is any.
});
const rootReducer = (state, action) => {
// When logout action is dispatched reset the action.
if (action.type === 'USER_LOG_OUT') {
state = undefined; // or to initial state if {} you want any data without session
}
return appReducer(state, action);
};
export default rootReducer;
您的 Home
组件需要一个从状态 selected 的用户对象。在这一点上,你应该 select 只是你想要的特定对象,state.users.current
,而不是 selecting state.users
然后查看 users.current
.
除非我们有用户,否则我们不希望 Home
呈现,因此我们可以 useEffect
有条件地离开页面。这意味着我们实际上不需要 await
注销,因为只要没有用户,导航就会自动发生。动作被分派 --> redux 状态改变 --> currentUser 属性改变 --> 效果运行 --> 导航发生。
const Home = (props) => {
const { navigation, currentUser } = props;
function Logout(id) {
// no async/await here
// navigation is triggered when currentUser updates
Auth.LogoutUser(id, props);
}
useEffect(() => {
if (!currentUser) {
navigation.navigate("Login");
}
}, [currentUser, navigation]);
if (!currentUser) {
// should only end up here momentarily while navigation is taking place
return null;
}
return (
<Container>
<Content>
<View style={Styles.content}>
<Text>Hi {currentUser.id}</Text>
<Button onPress={() => Logout(currentUser.id)}>
<Icon name="exit" />
</Button>
</View>
</Content>
</Container>
);
};
const mapStateToProps = (state) => {
return {
currentUser: state.users.current
};
};
export default connect(mapStateToProps)(Home);
在我的 React Native 应用程序中,实际上我需要使用导航和 redux 实现一个简单的注销,但是当我从主页发送注销操作时出现错误 (按下注销按钮), 因为在 Home 中我呈现当前用户并且在那一刻不存在。
我需要调度注销(删除当前用户)并在导航到登录页面后再次渲染主页或了解如何在渲染之前实现 componentWillMount.... 如何?
我的简历代码: (登录有效,我没有输入登录码)
App.tsx
import React, {useState} from 'react';
import { NavigationContainer, StackActions } from '@react-navigation/native';
//... many imports
const store = createStore(rootReducer);
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = { loading: true };
}
async componentDidMount() {
//... some code
}
render(){
if (this.state.loading) {
return (
<Root>
<AppLoading />
</Root>
);
}
else {
return (
<Provider store={store}>
<Root>
<NavigationContainer>
<Navigator/>
</NavigationContainer>
</Root>
</Provider>
);
}
}
}
Navigator.tsx
import React from 'react'
import { createStackNavigator } from '@react-navigation/stack'
import {connect} from 'react-redux'
import Login from '../Views/Login'
import Home from '../Views/Home'
const Stack = createStackNavigator();
const Navigator= (props) =>{
const {users} = props;
return (
<Stack.Navigator>
{console.log('Navigator here, '+users.current)}
{users.current ===null ?
(<>
<Stack.Screen name="Login" component={Login} options={{headerShown:false}}/>
</>)
: (<>
<Stack.Screen name="Home" component={Home} options={{headerShown:false}}/>
</>)
}
</Stack.Navigator>
);
}
const mapStateToProps=(state)=>{
const {users} = state;
return {users};
}
export default connect(mapStateToProps)(Navigator);
Home.tsx(注销后导航?)
import React from 'react'
import {Text, Container, Content, View, Button, Icon} from 'native-base'
import Styles from './Styles/HomeStyles'
import {connect} from 'react-redux'
import {Auth} from '../Services/Auth/AuthService'
const Home =(props) => {
const {navigation, users} = props;
return(
<Container >
<Content >
<View style={Styles.content}>
<Text>Hi {users.current.id}</Text>
<Button onPress={()=>Logout(users.current.id)} >
<Icon name='exit' />
</Button>
</View>
</Content>
</Container>
);
async function Logout(id:string){
console.log('Function start');
await Auth.LogoutUser(id, props);
navigation.navigate('Login');
}
}
const mapStateToProps=(state)=>{
const {users} = state;
return {users};
}
export default connect(mapStateToProps)(Home);
UserReducer.tsx
const Initial_State={
current:null
}
export function UserReducer(state=Initial_State, action:any){
switch (action.type){
case 'ADD_USER':
return{
...state,
current: action.user
};
case 'DELETE_USER':
return{
...state,
current: null
};
default:
return state;
}
}
AuthService.tsx(这里是dispatch)
export const Auth={
LoginUser,
LogoutUser
}
async function LogoutUser(id: string, props: any){
await props.dispatch({type : 'DELETE_USER', id});
}
async function LoginUser(AuthData:IAuthData, props: any){
//...some code
}
在您的情况下,您现在可以通过更改
来处理 users 变量的空状态 <Text>Hi {users.current.id}</Text>
至
<Text>Hi {users?.current?.id}</Text>
但在实际应用中,您应该必须重置完整的应用状态,并且必须在该应用状态上管理您的条件。
示例:
import { combineReducers } from 'redux';
import UsersReducer from './UsersReducer';
const appReducer = combineReducers({
users: UsersReducer,
// other Reducers if there is any.
});
const rootReducer = (state, action) => {
// When logout action is dispatched reset the action.
if (action.type === 'USER_LOG_OUT') {
state = undefined; // or to initial state if {} you want any data without session
}
return appReducer(state, action);
};
export default rootReducer;
您的 Home
组件需要一个从状态 selected 的用户对象。在这一点上,你应该 select 只是你想要的特定对象,state.users.current
,而不是 selecting state.users
然后查看 users.current
.
除非我们有用户,否则我们不希望 Home
呈现,因此我们可以 useEffect
有条件地离开页面。这意味着我们实际上不需要 await
注销,因为只要没有用户,导航就会自动发生。动作被分派 --> redux 状态改变 --> currentUser 属性改变 --> 效果运行 --> 导航发生。
const Home = (props) => {
const { navigation, currentUser } = props;
function Logout(id) {
// no async/await here
// navigation is triggered when currentUser updates
Auth.LogoutUser(id, props);
}
useEffect(() => {
if (!currentUser) {
navigation.navigate("Login");
}
}, [currentUser, navigation]);
if (!currentUser) {
// should only end up here momentarily while navigation is taking place
return null;
}
return (
<Container>
<Content>
<View style={Styles.content}>
<Text>Hi {currentUser.id}</Text>
<Button onPress={() => Logout(currentUser.id)}>
<Icon name="exit" />
</Button>
</View>
</Content>
</Container>
);
};
const mapStateToProps = (state) => {
return {
currentUser: state.users.current
};
};
export default connect(mapStateToProps)(Home);