Javascript 应用程序刷新时onAuthStateChanged Firebase侦听器导致私有路由问题
我目前已使用firebase初始化了React应用程序。在应用程序中,我使用react router dom创建了一个开放的登录路由和一个私有的家庭路由。我的app.js看起来是这样的:Javascript 应用程序刷新时onAuthStateChanged Firebase侦听器导致私有路由问题,javascript,reactjs,firebase,firebase-authentication,Javascript,Reactjs,Firebase,Firebase Authentication,我目前已使用firebase初始化了React应用程序。在应用程序中,我使用react router dom创建了一个开放的登录路由和一个私有的家庭路由。我的app.js看起来是这样的: import React, { useContext } from 'react' import { Route, Redirect } from 'react-router-dom' import { AppContext } from '../context/AppContext' const Priva
import React, { useContext } from 'react'
import { Route, Redirect } from 'react-router-dom'
import { AppContext } from '../context/AppContext'
const PrivateRoute = ({ component: Component, ...rest }) => {
const { currentUser } = useContext(AppContext)
return (
<Route
{...rest}
render={routeProps =>
!!currentUser ? (
<Component {...routeProps} />
) : (
<Redirect to={'/login'} />
)
}
/>
)
}
export default PrivateRoute
App.js:
import React from 'react'
import { BrowserRouter, Switch, Route } from 'react-router-dom'
import Login from './pages/Login'
import Home from './pages/Home'
import PrivateRoute from './utils/PrivateRoute'
const App = () => {
return (
<BrowserRouter>
<Switch>
<PrivateRoute exact path='/' component={Home} />
<Route path='/login' component={Login} />
</Switch>
</BrowserRouter>
)
}
export default App
从“React”导入React
从“react router dom”导入{BrowserRouter,Switch,Route}
从“./pages/Login”导入登录名
从“./pages/Home”导入主页
从“/utils/PrivateRoute”导入PrivateRoute
常量应用=()=>{
返回(
)
}
导出默认应用程序
我使用onAuthStateChanged firebase事件侦听器将currentUser存储在上下文中,如下所示:
AppContext:
import { useEffect, useState, createContext } from 'react'
import { auth } from '../utils/firebase'
export const AppContext = createContext()
export const AppProvider = ({ children }) => {
const [currentUser, setCurrentUser] = useState(null)
useEffect(() => {
auth.onAuthStateChanged(setCurrentUser)
}, [])
return (
<AppContext.Provider value={{ currentUser }}>
{children}
</AppContext.Provider>
)
}
从'react'导入{useffect,useState,createContext}
从“../utils/firebase”导入{auth}
export const AppContext=createContext()
export const AppProvider=({children})=>{
常量[currentUser,setCurrentUser]=useState(null)
useffect(()=>{
auth.onAuthStateChanged(setCurrentUser)
}, [])
返回(
{儿童}
)
}
当用户通过登录路径登录时:
登录:
import React, { useState, useCallback, useContext } from 'react'
import { auth } from '../utils/firebase'
import { useHistory, Redirect } from 'react-router-dom'
function Login() {
const [formData, setFormData] = useState({ email: '', password: '' })
const history = useHistory()
const handleChange = ({ target: { name, value } }) => {
setFormData({ ...formData, [name]: value })
}
const handleSubmit = useCallback(
async event => {
event.preventDefault()
await auth
.createUserWithEmailAndPassword(formData.email, formData.password)
.then(user => {
console.log(user)
history.push('/')
})
.catch(err => {
alert(err)
})
},
[history, formData.email, formData.password]
)
return (
<div className='form-container sign-up-container'>
<form className='register-form' onSubmit={handleSubmit}>
<h1>Create Account</h1>
<div className='social-container'>
<div className='social'>
<i className='fab fa-facebook-f'></i>
</div>
<div className='social'>
<i className='fab fa-google-plus-g'></i>
</div>
<div className='social'>
<i className='fab fa-linkedin-in'></i>
</div>
</div>
<span>or use your email for registration</span>
<input
type='email'
placeholder='Email'
name='email'
onChange={handleChange}
/>
<input
type='password'
placeholder='Password'
name='password'
onChange={handleChange}
/>
<button type='submit'>Sign Up</button>
</form>
</div>
)
}
export default Login
import React,{useState,useCallback,useContext}来自“React”
从“../utils/firebase”导入{auth}
从“react router dom”导入{useHistory,Redirect}
函数登录(){
const[formData,setFormData]=useState({电子邮件:'',密码:'})
const history=useHistory()
const handleChange=({target:{name,value}})=>{
setFormData({…formData,[名称]:值})
}
const handleSubmit=useCallback(
异步事件=>{
event.preventDefault()
等待授权
.createUserWithEmailAndPassword(formData.email,formData.password)
。然后(用户=>{
console.log(用户)
history.push(“/”)
})
.catch(错误=>{
警报(错误)
})
},
[历史记录,formData.email,formData.password]
)
返回(
创建帐户
或者使用您的电子邮件进行注册
注册
)
}
导出默认登录名
当前用户成功地存储在上下文中,用户被推送到私有主路由中
专用路线如下所示:
import React, { useContext } from 'react'
import { Route, Redirect } from 'react-router-dom'
import { AppContext } from '../context/AppContext'
const PrivateRoute = ({ component: Component, ...rest }) => {
const { currentUser } = useContext(AppContext)
return (
<Route
{...rest}
render={routeProps =>
!!currentUser ? (
<Component {...routeProps} />
) : (
<Redirect to={'/login'} />
)
}
/>
)
}
export default PrivateRoute
import React,{useContext}来自“React”
从“react router dom”导入{Route,Redirect}
从“../context/AppContext”导入{AppContext}
const privaterout=({component:component,…rest})=>{
const{currentUser}=useContext(AppContext)
返回(
!!当前用户(
) : (
)
}
/>
)
}
导出默认PrivateRoute
我遇到的问题是,当应用程序刷新时,currentUser最初变为null,然后currentUser的信息重新加载。当刷新时currentUser为null时,用户将从主路由踢出并重定向到登录页面。我想知道是否有人对如何防止这种情况发生有任何建议。您使用空值初始化
currentUser
状态变量:
const [currentUser, setCurrentUser] = useState(null)
这意味着当第一次加载页面时,currentUser
最初总是空的。在Firebase SDK异步加载之前,之前的用户对象直到一段时间后才能确定。您的代码需要为此做好准备。如果在呈现组件之前要求用户登录,则应等待第一次使用实际用户对象触发onAuthStateChanged
您可以在中阅读有关Firebase Auth SDK此行为的更多信息