【发布时间】:2021-06-08 12:09:40
【问题描述】:
对于我的一个小项目,我正在尝试尽可能实现最基本的身份验证,使用没有 Redux 的 React 上下文 API。
import { createContext, useContext, useState } from 'react'
export const AuthContext = createContext()
export const useAuth = () => {
const context = useContext(AuthContext)
if(context === null) throw new Error('Nope')
return context
}
export const AuthProvider = (props) => {
const [authenticated, setAuthenticated] = useState(false)
const login = () => {
setAuthenticated(true)
localStorage.setItem(storageKey, true)
}
const logout = () => {
setAuthenticated(false)
localStorage.setItem(storageKey, false)
}
return <AuthContext.Provider value={{authenticated, login, logout}} {...props}/>
}
export default AuthContext
我创建了一个上下文,并像这样将我的<App /> 组件包裹在其中; <AuthProvider></App></AuthProvider>。因为我想保持认证状态,所以我使用浏览器的本地存储来存储一个简单的布尔值。
import PrivateRoute from './PrivateRoute'
import { useAuth } from './context/AuthContext'
import { AuthPage } from './pages'
import {
BrowserRouter,
Switch,
Route,
} from 'react-router-dom'
import { useEffect } from 'react'
const App = () => {
const { login, authenticated } = useAuth()
useEffect(() => {
const token = localStorage.getItem('user')
if(token && token !== false) { login() }
})
return (
<BrowserRouter>
<Switch>
<PrivateRoute exact path="/auth" component={AuthPage} />
<Route exact path='/'>
Dashboard
</Route>
</Switch>
</BrowserRouter>
)
}
export default App
然后,在我的<App /> 组件中,我尝试调用从AuthProvider 给出的login 回调,这让我认为这让我在页面刷新期间登录。当我尝试访问当前组件中的authenticated 变量时,它确实有效。它表明我已通过身份验证。
但是,当我尝试设置 PrivateRoute 时,只有经过身份验证的用户才能这样访问:
import {
Route,
Redirect
} from 'react-router-dom'
import { useAuth } from './context/AuthContext'
const PrivateRoute = ({ component: Component, ...rest }) => {
const { authenticated } = useAuth()
if(authenticated) {
return <Route {...rest} render={(props) => <Component {...props} />} />
}
return <Redirect to={{ pathname: '/login' }} />
}
export default PrivateRoute
它不起作用。它只是将我重定向到登录页面。这是怎么来的? PrivateRoute 组件正在从 <App /> 组件呈现。还有,这个问题有什么解决办法?
【问题讨论】:
-
useEffect被调用 afterPrivateRoute组件已经挂载,当它调用它又调用login函数时,用户已经被重定向到@ 987654336@路线。 -
在
PrivateRoute组件内,仅在调用login函数后检查authenticated的值。创建了一个demo,向您展示如何解决问题。 (尝试更改useEffect挂钩内的token变量的值) -
上面的这个演示很棒。似乎最好只跟上身份验证的加载状态,这允许组件呈现,但您可以使用加载状态基本上等待身份验证发生。
标签: javascript reactjs react-router-dom react-context