使用异步存储反应本机导航问题

React Native navigation problem with asyc storage

我有一个非常奇怪的问题,到目前为止无法确定可能的弱点。

我有一个带有嵌套登录的 firebase 和 react-native 应用程序。

导航有问题。抽屉和堆栈导航工作正常,除了登录屏幕。

当我尝试登录并且 isSignedIn 变量变为真时,主屏幕的屏幕没有变化。它仍然是登录屏幕。但是,在控制台上,我看到身份验证成功。如果我返回代码并单击导航文件(已发布在此处)中的保存,强制重新加载似乎可以解决问题,我可以看到主屏幕。但这不是自动的。

好迷茫。

export default function Navigator() {

    const user = firebase.auth().currentUser;
    const [isSignedIn, setIsSignedIn] = useState(false)


    useEffect( () => {
        user ? setIsSignedIn(true) : setIsSignedIn(false)
        if (isSignedIn) storeData(user)
    })

    const storeData = async (value) => {
        try {
          await AsyncStorage.setItem('userObject', JSON.stringify(value))
            alert('Data successfully saved to the storage')
        } catch (e) {
            alert('Failed to save the data to the storage')
        }
      }

    return (
        <NavigationContainer>
        <Stack.Navigator initialRouteName="Login">
            {isSignedIn ? (
            <>
            <Stack.Screen name='loggedInUserNavigationStack' component={loggedInUserNavigationStack} options={{headerShown: false}}>
                </Stack.Screen>   
            </>
            ) : (
            <Stack.Screen name="Log in" component={LoginScreen} options={{headerShown: false}} />
            )}
        </Stack.Navigator>
    </NavigationContainer>
    );
}

function loggedInUserNavigationStack() {
    return (      
        <Drawer.Navigator initialRouteName="mainContentNavigator" drawerContent={ props => <DrawerContent {...props} /> }>
            <Drawer.Screen name="mainContentNavigator" component={mainContentNavigator} options={{ title: 'Home' }} />
            <Drawer.Screen name="About" component={AboutScreen} options={{ title: 'About' }}/>
            <Drawer.Screen name="Archive" component={ArchiveScreen} options={{ title: 'Archive' }}/>
            <Drawer.Screen name="Profile" component={ProfileScreen} options={{ title: 'Profile' }} />
            <Drawer.Screen name="Sign Out" component={SignOutScreen} options={{headerShown: false}}/>
        </Drawer.Navigator>
  );
}

function mainContentNavigator() {
    return (      
        <Stack.Navigator initialRouteName="HomeScreen">
            <Stack.Screen name="Home" component={HomeScreen} options={ 
                ({ navigation }) => {
                    return {
                      headerLeft: () => <Header navigation={navigation} />
                    }
                  }
                    } />
            <Stack.Screen name="CertainHabbit" component={CertainHabbit} options={({ route }) => ({ title: route.params.name })} />
        </Stack.Navigator>
  );
}

对 return 部分尝试以下操作:

return isSignedIn ? (
<NavigationContainer>
     <Stack.Screen name='loggedInUserNavigationStack' component={loggedInUserNavigationStack} options={{headerShown: false}} />
</NavigationContainer>
):(
<NavigationContainer>
     <Stack.Screen name="Login" component={LoginScreen} options={{headerShown: false}} />
</NavigationContainer>
)

请尝试,

<NavigationContainer>
     <Stack.Screen name="Login" component={LoginScreen} options={{headerShown: false}} />
</NavigationContainer>

你给的初始路线名称有initialRouteName="Login" 我确实在堆栈屏幕中看到 space。

当您加载页面时,Firebase 会自动尝试恢复登录用户。但由于这需要对服务器进行异步调用,因此可能需要一些时间。现在,在您的 const user = firebase.auth().currentUser 运行时,用户尚未通过身份验证。并且在身份验证完成时,您的代码并不知道它。

解决方案是使用身份验证状态侦听器,如 determining the signed in user 上文档的第一段所示。对你来说是这样的:

useEffect( () => {
  firebase.auth().onAuthStateChanged((user) => {
    setIsSignedIn(!!user);
    if (user) storeData(user)
  });
})