退出react应用程序会导致主屏幕中出现null指针



我正在开发一个带有登录页面的react应用程序。当用户成功登录时,后端返回一个用户对象(JSON(,其中包含一些用户属性(id、用户名…(以及JWT令牌。用户对象存储在AsyncStorage中(因此用户只需登录一次(。

try {
await AsyncStorage.setItem('authUser', JSON.stringify(data));
} catch (e) {
console.log(e.message);
}
dispatch({ type: 'SIGN_IN', authUser:data});

状态:

const [state, dispatch] = React.useReducer(
(prevState, action) => {
switch (action.type) {
case 'RESTORE_TOKEN':
return {
...prevState,
authUser: action.authUser,
isLoading: false,
};
case 'SIGN_IN':
return {
...prevState,
isSignout: false,
authUser: action.authUser,
};
case 'SIGN_OUT':
return {
...prevState,
isSignout: true,
authUser: null,
};
}
},
{
isLoading: true,
isSignout: false,
authUser: "",
}
);

第二次,我从AsyncStorage检索用户对象并将其传递到状态。

try {
authUser = await AsyncStorage.getItem('authUser');
} catch (e) {
console.log(e.message);
}
dispatch({ type: 'RESTORE_TOKEN', authUser: JSON.parse(authUser) });

我使用UserContext将authUser传递到我的欢迎屏幕:

<AuthContext.Provider value={authContext}>
<UserContext.Provider value={{authUser: state.authUser }}>
<NavigationContainer>
<RootStack.Navigator mode="modal" headerMode="none">
{state.isLoading ? (
<RootStack.Screen name="Splash" component={SplashScreen} />
) : state.authUser == null ? (
<RootStack.Screen name="Login" component={AuthenticationStackScreen} />
) : (
<RootStack.Screen name="Home" component={HomeScreen} />
)}
</RootStack.Navigator>
</NavigationContainer>
</UserContext.Provider>
</AuthContext.Provider>

在我的主屏幕上,我打印了一条包含用户名和signOut按钮的欢迎信息:

function HomeScreen(props) {
const { signOut } = React.useContext(AuthContext);
const { authUser } = React.useContext(UserContext);
return (
<View style={{ flex:1, alignItems: 'center', justifyContent: 'center', backgroundColor:'cyan' }}>
<Text>Hallo {authUser.username}</Text>
<Button title="Log out" onPress={signOut} />
<Text>HomeScreen </Text>
</View>
);
}

当用户登录或已经登录时,主屏幕将使用正确的用户名正确显示。单击注销按钮时会出现问题。authContext中的signOut方法被调用,该方法注销用户并从AsyncStorage:中删除对象

signOut: async () => {
try {
await AsyncStorage.removeItem('authUser');
} catch (e) {
console.log(e.message);
}
dispatch({ type: 'SIGN_OUT' })
}

问题:状态更改为SIGN_OUT,这将使我返回登录页面。但是由于我已经清除了用户对象,欢迎通知会抛出一个错误,因为{authUser.username}null:

TypeError: null is not an object (evaluating 'authUser.username')

单击注销按钮时,我没想到WelcomeScreen会被重新渲染。我是不是把应用程序的结构搞砸了,或者为什么会这样?如有任何关于如何解决这一问题的帮助,我们将不胜感激。提前感谢!

根据React文档,当上下文值发生变化时,useContext总是会重新呈现,所以这就是再次调用HomeScreen的原因。

您需要修复的另一件事是authUser初始状态等于authUser signOut状态:

const [state, dispatch] = React.useReducer(
(prevState, action) => {
switch (action.type) {
case 'RESTORE_TOKEN':
return {
...prevState,
authUser: action.authUser,
isLoading: false,
};
case 'SIGN_IN':
return {
...prevState,
isSignout: false,
authUser: action.authUser,
};
case 'SIGN_OUT':
return {
...prevState,
isSignout: true,
authUser: null,
};
}
},
{
isLoading: true,
isSignout: false,
authUser: "", //MAKE THIS THE SAME AS SIGN_OUT (null)
}
);

最新更新