Маршрутизатор с проверкой подлинности маршрутизатора React перенаправляет при обновлении страницы - PullRequest
0 голосов
/ 22 октября 2018

Моя проблема проста, по крайней мере, кажется.У меня есть состояние в моем магазине приставки, в котором хранится информация о том, вошел ли пользователь в систему или нет.Это все работает нормально, но когда пользователь обновляет страницу, на мгновение, пока аутентифицированное состояние асинхронно получает свои данные, рендеринг запускается и состояние не определено.

Так как состояние не определено, мой редирект на/ 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, и поскольку пользователь уже вошел в систему, он перенаправляется на домашний маршрут.

Есть идеи?

Ответы [ 4 ]

0 голосов
/ 23 октября 2018

Прежде всего, когда пользователь пытается войти в систему, вы получаете токен в ответ, когда пользователь проходит аутентификацию.теперь вы должны хранить токен в localStorage, используя

if(user.token){
   localStorage.setItem('user', JSON.stringify(user));
}

. Это означает, что когда вы используете токен в localalstorage, вы входите в систему, иначе вы выходите из системы.

теперь попробуйте установить состояние для перенаправления вдомашняя страница, если вы хотите перейти на домашнюю страницу после входа в систему.

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>
    )
}
}
0 голосов
/ 22 октября 2018

Хорошо, 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
    }
0 голосов
/ 23 октября 2018

Вы можете использовать реактив-роутер-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

0 голосов
/ 22 октября 2018

В идеале вы не должны обрабатывать маршрут сразу, а подождите, пока ваш запрос аутентификации не будет решен, и у вас будет четкое состояние.

Примерно так:

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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...