Я использую React Navigation в своем собственном приложении реакции и следит за процессом аутентификации.
app. js отобразит экран аутентификации или домашний экран на основе состояния аутентификации пользователя, называемого userProfile.
userProfile будет передаваться из компонента App в дочерний компонент через контекст React, называемый userContext, и некоторые функции диспетчеризации также будут передаваться как authContext.
const App: () => React$Node = () => {
const [state, dispatch] = React.useReducer(
(prevState, action) => {
switch (action.type) {
case SIGN_IN:
return {
...prevState,
userProfile: action.userProfile,
};
case SIGN_OUT:
return {
...prevState,
userProfile: null,
};
}
},
{
isLoading: true,
userProfile: null,
}
)
React.useEffect(() => {
isMountedRef.current = true;
return () => (isMountedRef.current = false);
}, []);
const authContext = React.useMemo(
() => ({
signIn: async userProfile => {
try {
await AsyncStorage.setItem('userProfile', JSON.stringify(userProfile))
dispatch({ type: SIGN_IN, userProfile })
} catch (error) {
console.log(error)
}
},
signOut: async () => {
try {
await AsyncStorage.removeItem('userProfile');
dispatch({ type: SIGN_OUT })
} catch (error) {
console.log(error)
}
}
}),
[]
);
return (
<AuthContext.Provider value={{authContext, userContext: state.userProfile}}>
<NavigationContainer ref={navigationRef}>
<Stack.Navigator>
{console.log('app render: ', state.userProfile)}
{
state.userProfile == null ?
(<Stack.Screen name="AuthContainer" component={AuthContainer} options={{ headerShown: false }} />) :
(<Stack.Screen name="MainContainer" component={MainContainer} options={{ headerShown: false }} />)
}
</Stack.Navigator>
</NavigationContainer>
</AuthContext.Provider>
);
};
В одном из вложенных дочерних компонентов ProfileScreen под домашним экраном или под MainContainer в приведенном выше коде я пытаюсь использовать userContext для отображения информации о пользователе на экране, и Кнопка «Выйти» использует функцию выхода из диспетчеризации, чтобы обновить состояние аутентификации пользователя до нуля в компоненте приложения.
function ProfileScreen() {
const { authContext, userContext } = React.useContext(AuthContext)
console.log('profile render: ', userContext)
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Hello {userContext.username}!</Text>
<Text>Profile Screen</Text>
<Button
title="Sign Out"
onPress={() => authContext.signOut()}
/>
</View>
);
}
export default ProfileScreen;
После отправки функции выхода я ожидаю, что приложение перейдет к экрану авторизации AuthContainer, чтобы попросить пользователя выполнить вход еще раз, поскольку в это время мое состояние userProfile в компоненте приложения должно быть нулевым Однако компонент App все еще пытается отобразить ProfileScreen, который выдает ошибку userContext, равную null.
Из моего журнала, после отправки функции выхода в ProfileScreen, он показывает
app render: null ---> App re-render
profile render: null ---> profileScreen re-render
profile render: null ---> profileScreen re-render
auth container ---> finally start rendering Auth Screen
, а затем сразу выбрасывает userContext - пустая ошибка
Может ли кто-нибудь помочь мне понять, почему Компонент приложения пытается отобразить profileScreen, когда состояние userProfile равно нулю? И почему profileScreen перерисовывает дважды?
Огромное спасибо