[英]React router authenticated route is redirecting when I refresh the page
我的問題很簡單,至少看起來如此。 我的redux存儲中有一個狀態,該狀態保存用戶是否已登錄的狀態。 一切正常,但是當用戶刷新頁面時,在經過身份驗證的狀態異步獲取其數據的瞬間,渲染運行且狀態未定義。
因為狀態是不確定的,所以我重定向到/ login會運行,因此刷新會將我踢出應用程序,然后返回登錄,然后檢查是否已經登錄並將我帶到主頁。
有關如何解決此問題的任何想法:
{
!this.props.authenticated && (
<Switch>
<Route path="/login" component={LoginForm} />
<Route path="/register" component={RegisterForm} />
<Route path="" render={props => {
return <Redirect to="/login" />
}}
/>
</Switch>
)
}
因此,當this.props.authenticated在短時間內為false時,它將命中登錄重定向。 但是,幾毫秒后,this.props.authenticated為true,並且由於用戶已經登錄,因此將重定向到本地路由。
有任何想法嗎?
理想情況下,您不會立即渲染路由,而是要等到身份驗證請求解決並且狀態清晰之后再進行渲染。
像這樣:
class App extends React.Component { constructor( props ) { super( props ); this.state = { // You could just check if authenticated is null, // but I think having an extra state makes is more clear isLoading: true, authenticated: null, }; this.checkAuthentication(); } checkAuthentication() { // Some async stuff checking against server // I'll simulate an async call with this setTimeout setTimeout( () => this.setState( { authenticated: Boolean( Math.round( Math.random() ) ), isLoading: false, } ), 1000 ); } render() { // Render a loading screen when we don't have a clear state yet if ( this.state.isLoading ) { return <div>loading</div>; } // Otherwise it is safe to render our routes return ( <div> routes,<br /> random authenticated: <strong> { this.state.authenticated.toString() } </strong> </div> ); } } ReactDOM.render( ( <App /> ), document.querySelector( 'main' ) );
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> <main></main>
好的,lumio通過setTimeout幫助我走上了正確的軌道,所以我改用async / await解決了這個問題:
class App extends Component {
state = {
error: "",
isLoading: true,
}
async componentDidMount() {
let token = localStorage.getItem('jwtToken');
if (token) {
setAuthToken(token);
await this.props.isAuthenticatedAction(true);
} else {
await this.props.isAuthenticatedAction(false);
}
this.setState({
isLoading: false,
});
}
handleLogout = (evt) => {
evt.preventDefault();
localStorage.removeItem('jwtToken');
window.location.reload();
}
render() {
if (this.state.isLoading) {
return <div></div>;
} else {
// return my regular content
}
您可以將react-router-dom用於身份驗證工作流程。
import React from "react";
import {
BrowserRouter as Router,
Route,
Link,
Redirect,
withRouter
} from "react-router-dom";
////////////////////////////////////////////////////////////
// 1. Click the public page
// 2. Click the protected page
// 3. Log in
// 4. Click the back button, note the URL each time
const AuthExample = () => (
<Router>
<div>
<AuthButton />
<ul>
<li>
<Link to="/public">Public Page</Link>
</li>
<li>
<Link to="/protected">Protected Page</Link>
</li>
</ul>
<Route path="/public" component={Public} />
<Route path="/login" component={Login} />
<PrivateRoute path="/protected" component={Protected} />
</div>
</Router>
);
const fakeAuth = {
isAuthenticated: false,
authenticate(cb) {
this.isAuthenticated = true;
setTimeout(cb, 100); // fake async
},
signout(cb) {
this.isAuthenticated = false;
setTimeout(cb, 100);
}
};
const AuthButton = withRouter(
({ history }) =>
fakeAuth.isAuthenticated ? (
<p>
Welcome!{" "}
<button
onClick={() => {
fakeAuth.signout(() => history.push("/"));
}}
>
Sign out
</button>
</p>
) : (
<p>You are not logged in.</p>
)
);
const PrivateRoute = ({ component: Component, ...rest }) => (
<Route
{...rest}
render={props =>
fakeAuth.isAuthenticated ? (
<Component {...props} />
) : (
<Redirect
to={{
pathname: "/login",
state: { from: props.location }
}}
/>
)
}
/>
);
const Public = () => <h3>Public</h3>;
const Protected = () => <h3>Protected</h3>;
class Login extends React.Component {
state = {
redirectToReferrer: false
};
login = () => {
fakeAuth.authenticate(() => {
this.setState({ redirectToReferrer: true });
});
};
render() {
const { from } = this.props.location.state || { from: { pathname: "/" } };
const { redirectToReferrer } = this.state;
if (redirectToReferrer) {
return <Redirect to={from} />;
}
return (
<div>
<p>You must log in to view the page at {from.pathname}</p>
<button onClick={this.login}>Log in</button>
</div>
);
}
}
export default AuthExample;
請參閱鏈接https://reacttraining.com/react-router/web/example/auth-workflow
首先,當用戶嘗試登錄時,您將在身份驗證后收到令牌作為響應。 現在您必須使用以下命令將令牌存儲在localStorage中
if(user.token){
localStorage.setItem('user', JSON.stringify(user));
}
這表明當您在本地存儲中有令牌時,您將登錄,否則將注銷。
現在,如果您要在登錄后進入主頁,請嘗試設置狀態以重定向到主頁。
this.setState({redirectToReferrer: true});
現在返回重定向到願望頁面
if (this.state.redirectToReferrer){
return (<Redirect to={'/home'}/>)
}
login.js
import React from 'react';
import axios from 'axios';
import {Redirect} from 'react-router-dom';
export default class Login extends React.Component{
constructor(props){
super(props);
this.state = {
email : '' ,
password : '',
redirectToReferrer : false
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event){
this.setState({
[event.target.name] : event.target.value
});
}
handleSubmit(event){
event.preventDefault();
const user = {
email : this.state.email,
password : this.state.password
};
if(this.state.email && this.state.password)
{
axios.post(`{Api}/login`,user)
.then((response) =>
{
let userresponse = response;
console.log(userresponse.data);
if(userresponse.token){
sessionStorage.setItem('data',JSON.stringify(userresponse));
this.setState({redirectToReferrer: true});
}
},this)
.catch((error) => alert(error))
}
}
render(){
if (this.state.redirectToReferrer){
return (<Redirect to={'/user'}/>)
}
if (sessionStorage.getItem('data')){
return (<Redirect to={'/user'}/>)
}
return(
<div>
<form ref="formdemo" onSubmit={this.handleSubmit}>
<label>
Username:
<input type="email" name="email" onChange={this.handleChange} placeholder="Enter Your EmailID" required/></label><br/>
<label>
Password :
<input type="password" name="password" onChange={this.handleChange} placeholder="Enter Your Password" required/></label><br/>
<input type="submit"/>
</form>
</div>
)
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.