使用带有 Redux 和 Firebase 身份验证的 React-Navigation v5

Posted

技术标签:

【中文标题】使用带有 Redux 和 Firebase 身份验证的 React-Navigation v5【英文标题】:Using React-Navigation v5 with Redux & Firebase Authentication 【发布时间】:2020-08-02 14:04:54 【问题描述】:

我正在尝试使用 React-Navigation 版本 5(不是版本 4)在用户登录时从身份验证屏幕/堆栈切换到非身份验证屏幕/堆栈。一个简单的例子在文档中得到了很好的证明。

但是,文档没有提供使用 ReduxGoogle Firebase 身份验证的详细信息。成功登录后,我收到以下警告消息。

Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.

我认为这个警告信息的原因是调用 Redux 动作(动作创建者)导致重新渲染认证屏幕,而导航代码已经卸载了这个屏幕! 身份验证屏幕卸载后如何更新 Redux 的 store?

导航代码:

...
// If user is logged in -> display the app/main stack
if (props.loggedIn) 

    const MyTabs = createBottomTabNavigator();
    return (
        <NavigationContainer>
            <MyTabs.Navigator initialRouteName="UserTypeScreen">
                <MyTabs.Screen name="UserTypeScreen" component=UserTypeScreen  />
                <MyTabs.Screen name="PermissionsScreen" component=PermissionsScreen />
            </MyTabs.Navigator>
        </NavigationContainer>
    ); 

// If user is NOT logged in -> display the auth stack
else 
    const AuthStack = createStackNavigator();
    return (
        <NavigationContainer>
            <AuthStack.Navigator>
                <AuthStack.Screen name="AuthScreen" component=AuthScreen />
                <AuthStack.Screen name="AuthLinkScreen" component=AuthLinkScreen />
            </AuthStack.Navigator>
        </NavigationContainer>
    ); 

...

认证画面:

...
useEffect( () => 
    const unSubscribe = firebase.auth().onAuthStateChanged( (user) => 
        if (user) 
            const idToken = firebase.auth().currentUser.getIdToken(); 
            const credential = firebase.auth.PhoneAuthProvider.credential(idToken); 

            // The following statement causes a warning message, because it causes re-rendering of an unmounted screen
            props.acLoginUserSuccess(user, credential); 
         
    ); 

    return () => 
        unSubscribe();
    ;
, []); 
...

Redux Action Creator:

...
export const acLoginUserSuccess = (user, credential) => 
    return 
        type: LOGIN_USER_SUCCESS,
        payload:  user: user, credential: credential 
  ;
;
...

【问题讨论】:

【参考方案1】:

我已经快速浏览了你的代码,但这是我的想法(可能是错误的)。

文档建议在已安装的屏幕上获取令牌(示例中为 App.js)。

如果 useEffect 挂钩中的 firebase.auth() 侦听器位于 App.js 中,这将不是问题。

我认为显示警告消息是因为当您在 MyTabs 路由中时,未安装 AuthScreen。

将侦听器移动到 App.js 或与 auth 和 MyTabs 屏幕位于同一堆栈的屏幕上将解决我认为的问题。

【讨论】:

谢谢。事实上,我试过了。但是,我找不到从 App.js 中更新 Redux 状态的方法。我认为不可能定义提供者(Redux)并使用它来更新同一组件中的状态。换句话说,似乎不可能将 Redux 定义为组件中的提供者,并使用“连接”组件来访问该组件中的状态,其中 Redux 被定义为提供者!抱歉,没有代码示例很难解释。如果我未能传达这个想法,请告诉我。我会用这方面的信息更新我的问题。 你可以导入 store 并做 store.dispatch(action)【参考方案2】:

我相信下面的代码是用获取令牌并存储在 Redux 存储中的想法编写的。

是否可以在凭据验证成功后移动此逻辑而不是 卸载?

请提供卸载此逻辑以更好地评估问题的正当理由

firebase.auth().onAuthStateChanged( (user) => 
    if (user) 
        const idToken = firebase.auth().currentUser.getIdToken(); 
        const credential = firebase.auth.PhoneAuthProvider.credential(idToken); 

        // The following statement causes a warning message, because it causes re-rendering of an unmounted screen
        props.acLoginUserSuccess(user, credential); 
     
);

【讨论】:

以上是关于使用带有 Redux 和 Firebase 身份验证的 React-Navigation v5的主要内容,如果未能解决你的问题,请参考以下文章

Redux firebase - 正确处理身份验证状态(前几毫秒状态为空,直到加载)

为啥我无法通过 Firebase 的身份验证?

使用 React Redux Redux-Thunk 进行 Firebase 身份验证

如何使用 React Redux 实现 Firebase 身份验证?

使用 React 和 react-redux-firebase 在登录期间确定范围

如何在通过 Redux 操作进行身份验证后重定向用户?