javascript - 登录后Reactjs重定向到受保护的页面在身份验证后不起作用
问题描述
登录后路由器无法重定向到受保护的页面。我已经建立了一个登录页面,/login
并且在登录后应该重定向到/dashboard
而不是停留在那里我在这里做错了什么。
这是我的代码的要点,或者这是我的完整代码的 github链接
登录页面代码
import React, { useState } from 'react'
import {
CButton,
CCard,
CCardBody,
CCardGroup,
CCol,
CContainer,
CForm,
CFormFeedback,
CFormInput,
CInputGroup,
CInputGroupText,
CRow,
} from '@coreui/react'
import CIcon from '@coreui/icons-react'
import { cilLockLocked, cilUser } from '@coreui/icons'
import axios from 'axios'
import qs from 'qs'
import Auth from '../../../Auth/Auth'
const Login = () => {
const [validated, setValidated] = useState(false)
const [error, setError] = useState(null)
const [username, setUsername] = useState('')
const [password, setPassword] = useState('')
function handleChange(e) {
const { name, value } = e.target
setError(null)
switch (name) {
case 'username':
setUsername(e.target.value)
break
case 'password':
setPassword(e.target.value)
break
}
e.preventDefault()
}
const handleSubmit = (event) => {
const bodyFormData = new FormData()
const form = event.currentTarget
Auth.authenticate()
setError(null)
setValidated(true)
}
return (
<div className="bg-light min-vh-100 d-flex flex-row align-items-center">
<CContainer>
<CRow className="justify-content-center">
<CCol md={8}>
<CCardGroup>
<CCard className="p-4">
<CCardBody>
<CForm
className="row g-3 needs-validation"
noValidate
validated={validated}
onSubmit={handleSubmit}
>
<h1>Login</h1>
<p className="text-medium-emphasis">Sign In to your account</p>
<CInputGroup className="mb-3">
<CInputGroupText>
<CIcon icon={cilUser} />
</CInputGroupText>
<CFormInput
id="username"
name="username"
placeholder="Username"
autoComplete="username"
onChange={handleChange}
required
/>
<CFormFeedback invalid>Please input Username</CFormFeedback>
</CInputGroup>
<CInputGroup className="mb-4">
<CInputGroupText>
<CIcon icon={cilLockLocked} />
</CInputGroupText>
<CFormInput
id="password"
name="password"
type="password"
placeholder="Password"
autoComplete="current-password"
onChange={handleChange}
required
/>
<CFormFeedback invalid>Please input password</CFormFeedback>
</CInputGroup>
<CRow>
<CCol xs={6}>
<CButton color="primary" type="submit" className="px-4">
Login
</CButton>
{error}
</CCol>
</CRow>
{/*<CRow>*/}
{/* <CCol xs={6}>{error}</CCol>*/}
{/*</CRow>*/}
</CForm>
</CCardBody>
</CCard>
</CCardGroup>
</CCol>
</CRow>
</CContainer>
</div>
)
}
export default Login
Auth.js 文件
const Auth = {
isAuthenticated: false,
authenticate() {
this.isAuthenticated = true
},
signout() {
this.isAuthenticated = false
},
getAuth() {
return this.isAuthenticated
},
}
export default Auth
应用程序.js 文件
import React, { Component } from 'react'
import { HashRouter, Redirect, Route, Switch } from 'react-router-dom'
import './scss/style.scss'
import Dashboard from './views/dashboard/Dashboard'
import Auth from './Auth/Auth'
const loading = (
<div className="pt-3 text-center">
<div className="sk-spinner sk-spinner-pulse"></div>
</div>
)
// Containers
const DefaultLayout = React.lazy(() => import('./layout/DefaultLayout'))
// Pages
const Login = React.lazy(() => import('./views/pages/login/Login'))
const PrivateRoute = ({ component: Component, ...rest }) => (
<Route
{...rest}
render={(props) =>
Auth.getAuth() ? (
<Component {...props} />
) : (
<Redirect
to={{
pathname: '/',
}}
/>
)
}
/>
)
class App extends Component {
render() {
return (
<HashRouter>
<React.Suspense fallback={loading}>
<Switch>
<Route exact path="/login" name="Login Page" render={(props) => <Login {...props} />} />
{/*<Route path="/" name="Home" render={(props) => <DefaultLayout {...props} />} />*/}
<Route exact path="/" name="Login Page" render={(props) => <Login {...props} />} />
<PrivateRoute
path="/dashboard"
name="Dashboard Page"
render={(props) => <Dashboard {...props} />}
/>
</Switch>
</React.Suspense>
</HashRouter>
)
}
}
export default App
解决方案
我以稍微不同的方式实现了这个,它可以工作,所以我要分享它,也许它有帮助:
这类似于您的PrivateRoute
:
const ProtectedRoute = (props) => {
const { state } = useOvermind();
return (
<Route {...props}>
{state.user.isLoggedIn === true && props.children}
{state.user.isLoggedIn !== true && <Redirect to="/login" />}
</Route>
);
};
然后在 App.js 我有:
(...)
<Router>
<Switch>
<Route path="/login" component={LoginScreen} />
<Route path="/">
<ProtectedRoute exact={true} path="/">
<DashboardScreen />
</ProtectedRoute>
{state.user.isAdmin && (
<ProtectedRoute path="/users">
<UsersScreen />
</ProtectedRoute>
)}
<ProtectedRoute path="/suppliers">
<SuppliersScreen />
</ProtectedRoute>
</Route>
</Switch>
</Router>
(...)
在登录屏幕上我有:
const LoginScreen = (props) => {
const { state } = useOvermind();
return (
<>
{state.user.isLoggedIn && <Redirect to="/" />}
{!state.user.isLoggedIn && (
(... rest of code here...)
)}
</>
);
};
就像克里斯刚刚在评论中提到的那样,您需要更新您的状态才能使代码正常工作。在我的例子中,我使用 Overmind 进行状态管理,并在成功的 Login api 调用之后更新user.isLoggedIn
(以 开头false
)为。true
同样在 App.js 上,我只是在渲染函数中显示代码,特别是与Router
.
在 App.jsstate.user.isAdmin
上,如果用户是管理员,我还使用另一个布尔值 ( ) 仅显示指向用户屏幕的链接。当然,在Users
屏幕里面我也有一个验证,和Login
屏幕上的类似,验证是否state.user.isAdmin===true
允许渲染屏幕,否则再次重定向到主屏幕(<Redirect to="/" />
)。
推荐阅读
- swift - Swift (macOS):使用文件启动 TextEdit
- java - 如何从 Web 应用程序中预选特定打印机
- angular - shareReplay 更改顺序
- java - 如何将 Java 应用程序代码指标检测到 Prometheus
- r - 如何以编程方式向 R 中的交互式函数提供用户输入(特别是在总人口普查包中)
- html - html/css - 以可变数量的颜色拆分 td
- php - 如何使用 Endroid\QR Code 设置 QR 版本
- reactjs - 如何使用下拉列表中的选定选项创建新表?
- php - 如何使用 EOF、NUL、DLE 等 php 删除解密的 .eml 文件中的控制字符
- mysql - 计算两个日期之间的特定日期计数