簡體   English   中英

當我刷新頁面時,React路由器認證的路由正在重定向

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM