使用 React、React-Router 保留 Google 身份验证信息

时间:2021-01-16 01:31:07

标签: reactjs firebase-authentication react-router google-authentication use-effect

我希望在多个页面上保持身份验证,但每次加载页面时,都会重新加载凭据,而不是看到已被检索。可能只是我误解了这将如何工作,但我很高兴听到有关此问题的最佳实践。

我正在使用 Firebase/Google 身份验证,并且

想使用他们的onAuthStateChanged函数,存储不同页面之间的凭证信息。在我看来,这将被视为相同的“会话”,尽管我来自移动背景并且可能误解了网络概念。

onAuthStateChanged 每次我路由到一个不是最大交易的新页面时都会被点击,但我也希望保留我使用 Firebase 返回的信息获取的其他用户信息。因此,在每次加载页面时,onAuthStateChanged 都会被触发,并且没有任何持久性,因此我需要重新检索我需要的其他用户信息。

我会列出代码,然后进一步澄清问题。

1。代码设置

首先,我有自己的 App 类:

import React, { useEffect } from 'react'
import Navigation from './components/Navbar'
import Routes from './Routes'
import { AuthProvider } from './services/contexts/AuthContext'

function App() {
  return (
    <AuthProvider>
      <Navigation />
      <Routes />
    </AuthProvider>
  )
}

export default App

路线非常简单。为简洁起见,它类似于:

import React, { Component } from 'react'
import { Router, Switch, Route } from 'react-router-dom'

import Home from './pages/Home'
import history from './history'
import Pricing from './pages/Pricing'
import PrivateRoute from './PrivateRoute'
import Account from './pages/Account'

export default class Routes extends Component {
  render() {
    return (
      <Router history={history}>
        <Switch>
          <Route path="/" exact component={Home} />
          <Route path="/pricing" component={Pricing} />
          <PrivateRoute path="/account" component={Account} />
        </Switch>
      </Router>
    )
  }
}

导航就像:

import React from 'react'
import { Navbar, Nav } from 'react-bootstrap'
import { withRouter } from 'react-router-dom'

import { useAuth } from '../services/contexts/AuthContext'

const Navigation = (props) => {
  const { currentUser } = useAuth()

  // console.log(props)
  return (
    <Navbar className="navbarColor" variant="dark">
      <Navbar.Toggle aria-controls="basic-navbar-nav" />
      <Navbar.Collapse id="basic-navbar-nav">
        <Nav className="mr-auto">
          <Nav.Link href="/">Home</Nav.Link>
          {!currentUser && <Nav.Link href="/pricing">Pricing</Nav.Link>}
          {currentUser && <Nav.Link href="/account">Account</Nav.Link>}
        </Nav>
      </Navbar.Collapse>
    </Navbar>
  )
}

export default withRouter(Navigation)

最后,授权处理看起来像这样:

import React, { useContext, useEffect, useState } from 'react'
import { auth } from '../Authentication/firebase'

const AuthContext = React.createContext()

export function useAuth() {
  return useContext(AuthContext)
}

export const AuthProvider = ({ children }) => {
  const [currentUser, setCurrentUser] = useState()
  const [loading, setLoading] = useState(true)

  useEffect(() => {
    const unsubscribe = auth.onAuthStateChanged(async (user) => {
      console.log('setting up user')
      setCurrentUser(user)
      // Fetch other user information, like subscription, from my own database
      setLoading(false)
    })

    return unsubscribe
  }, [])

  const value = {
    currentUser
  }
  return (
    <AuthContext.Provider value={value}>
      {!loading && children}
    </AuthContext.Provider>
  )
}

2.进一步的问题澄清

我已将 onAuthStateChanged 放在 useEffect 中,并将路由器包裹在 AuthContext 中,这让我认为任何路由都会使用相同的上下文,因此 {{1} } (不带参数)不会被再次调用。并不是 useEffect 被多次触发,而是整个组件似乎都被重新创建,让我觉得这个问题可能与我错误地做了一些事情有关,而不必绝对重新渲染一切。

我希望这很清楚;如果我需要澄清任何事情或提供任何进一步的信息,请告诉我。

更新

我意识到它没有按照我想要的方式“加载”的部分原因是我进行身份验证设置的方式,在 useEffect 被标记为 true 之前不会返回子视图。至少在视觉上我通过添加 loading 改进了这一点,以便某些共享元素(如导航栏)可以在等待身份验证过程时加载。

这本身并不是我的问题的答案,所以听到人们如何以最佳方式处理存储身份验证仍然很高兴。

0 个答案:

没有答案