Firebase onAuthStateChange 是不是应该自动触发页面重定向?

Posted

技术标签:

【中文标题】Firebase onAuthStateChange 是不是应该自动触发页面重定向?【英文标题】:Is Firebase onAuthStateChange supposed to automatically trigger a page redirect?Firebase onAuthStateChange 是否应该自动触发页面重定向? 【发布时间】:2019-10-24 06:27:41 【问题描述】:

我的应用需要在用户登录时执行一系列 Redux 调度。这些调度必须在用户被重定向到基于商店状态的页面之前完成。通过一些调试,我发现似乎在用户登录并触发 Firebase 的 onAuthStateChanged 侦听器后,页面会自动将用户重定向到登录页面(然后由 react-router 重定向)而不是当我声明重定向时。 有没有办法防止这种行为?

起初,我认为重定向是由调度触发的,但经过一些调试后,我将行为范围缩小到身份验证更改。一旦用户已经通过身份验证并执行页面刷新,我就可以验证一切是否按预期工作。

// A bunch of imports before this

const store = configureStore()

const jsx = (
    <Provider store=store>
        <AppRouter />
    </Provider>
)

let hasRendered = false

const renderApp = () => 
    if (!hasRendered) 
        store.dispatch(setApi()).then(() => 
            ReactDOM.render(jsx, document.getElementById('app'))
        )
        hasRendered = true
    


ReactDOM.render(<LoadingPage />, document.getElementById('app'))

firebase.auth().onAuthStateChanged(async (user) => 
    if (user) 
        console.log('logged in')
        store.dispatch(login(user.uid))
        await store.dispatch(startGetProfiles(user.uid))

        const profiles = store.getState().profiles
        const selectedCharacterId = localStorage.getItem('selectedCharacterId')
        const profileId = selectedCharacterId || profiles.length === 1 && profiles[0].id

        if (profileId) 
            await store.dispatch(startSetProfile(user.uid, profileId))
         
        const profile = store.getState().profile

        renderApp()

        if (!!profile.id) 
            history.push('/profile')
         else if (profiles.length > 0) 
            history.push('/select')
         else 
            history.push('/create')
        
     else 
        console.log('logged out')
        store.dispatch(logout())
        renderApp()
        history.push('/')
    
)

我希望页面重定向仅在我使用 history.push('/somepage') 时发生,但重定向会在用户登录后立即触发。

【问题讨论】:

“Firebase onAuthStateChange 是否应该自动触发页面重定向?”没有。它不是,也不是。如果您在if (user) 上设置断点,当您在调试器中运行代码时会触发它吗?如果是这样,当您逐步执行该方法的其余部分时,哪一行没有按照您的预期执行? Welp,我刚刚学会了如何实际调试,非常感谢。在深入研究之后,似乎页面刷新是在store.dispatch(login(user.uid)) 调用之后立即发生的。此外,事实证明 else 块中的 history.push('/') 调用不是必需的,因为页面在 store.dispatch(logout()) 调用之后重定向,这似乎加强了我的怀疑,即 firebase 在执行登录/注销后触发页面刷新过程。 这不太可能,但当然也不是不可能。您可以尝试在 jsbin 之类的网站上仅使用 Firebase 身份验证 SDK 重现它,以便我看看吗?请参阅how to create a minimal, complete, verifiable example,了解有关最小化重现问题所需代码的更多提示,以及为什么这很重要。 【参考方案1】:

好的,这就是我学到的东西 - 似乎正在发生的事情是,当我的路线中的道具发生变化时,正在发生刷新。我的所有路线如下所示:

export const PrivateRoute = (
    isAuthenticated,
    component: Component,
    ...rest
) => (
    <Route ...rest component=(props) => (
        isAuthenticated ? (
            <Component ...props />     
        ) : (
            <Redirect to="/" />
        )
    ) />
)

const mapStateToProps = (state) => (
    isAuthenticated: !!state.auth && !!state.auth.uid
)

export default connect(mapStateToProps)(PrivateRoute)

请注意我是如何使用 Redux 在路由用户之前检查用户是否经过身份验证的。当向我的商店发送登录/注销操作的调用更新 auth 值时,这会更新 isAuthenticated 的路由属性,从而触发组件和路由链的更新。为了解决这个问题,我基本上必须创建新路由来处理路由器在更新时所做的事情,并从我的onAuthStateChanged 代码中删除history.push() 调用。

所以要回答我的问题,Firebase 不会触发页面重定向。将 Redux 与 React-Router 结合使用时,请注意路由道具的更改可能会触发组件更新和重新路由发生。

【讨论】:

以上是关于Firebase onAuthStateChange 是不是应该自动触发页面重定向?的主要内容,如果未能解决你的问题,请参考以下文章

firebase.auth().onAuthStateChanged 不工作

如何从 firebase.auth().onAuthStateChanged 中提取数据

.onAuthStateChanged 方法是不是计入 Firebase 身份验证验证?

TypeError: firebase.auth(...).onAuthStateChanged 不是函数

在哪里放置 firebase.auth().onAuthStateChanged()

使用 useEffect 与 onAuthStateChanged 检测 Firebase 用户更改 - 有啥区别?