当我刷新页面时,React路由器认证的路由正在重定向

时间:2018-10-22 19:37:38

标签: javascript react-router

我的问题很简单,至少看起来如此。我的redux存储中有一个状态,该状态保存用户是否已登录的状态。一切正常,但是当用户刷新页面时,在经过身份验证的状态异步获取其数据的瞬间,渲染运行并且状态未定义。

由于状态未定义,我的重定向到/ login会运行,因此刷新会将我踢出应用程序并返回登录,然后登录查看我是否已经登录并将我带到主页。 / p>

有关如何解决此问题的任何想法:

  {
    !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,并且由于用户已经登录,因此将重定向到本地路由。

有什么想法吗?

4 个答案:

答案 0 :(得分:1)

理想情况下,您不会立即渲染路由,而是要等到身份验证请求得到解决并且状态为清除状态。

类似这样的东西:

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>

答案 1 :(得分:0)

好的,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
    }

答案 2 :(得分:0)

您可以将react-router-dom用于身份验证工作流程。

@RequestMapping('/service/subDirectoryOfService')
public String subDirectoyOfService(@FormParam String params){
      JSONObject json = new JSONObject(params);
      String base64 = json.getString("attachedFile");
      System.out.println("base64 of file: "+ base64);
      return "{\"res\":\"success\"}"
}

引用链接https://reacttraining.com/react-router/web/example/auth-workflow

答案 3 :(得分:0)

首先,当用户尝试登录时,您将在身份验证后收到令牌作为响应。现在您必须使用

将令牌存储在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>
    )
}
}