Перенаправить маршрутизатор после входа в систему - PullRequest
0 голосов
/ 30 августа 2018

Я пытаюсь выяснить, как перенаправить приложение реакции на соответствующую страницу после того, как оно было аутентифицировано через логин.

Вот мой файл App.js с маршрутизацией (без импорта):

ReactDOM.render((
<Provider store={store}>
    <Router history={history}>
        <Switch>
            <PrivateRoute path="/test" component={Test} />
            <Route path="/login" component={Login}  />
            <PrivateRoute path="/" render={() => <h1>Welcome</h1>} />
        </Switch>
    </Router>
</Provider>
), document.getElementById('root'));

Я использую компонент PrivateRoute для проверки подлинности частных маршрутов:

class PrivateRoute extends Route {
render() {
    const { component: Component, isAuthenticated } = this.props;

    let propsCopy = Object.assign({}, this.props);
    delete propsCopy.component;
    delete propsCopy.isAuthenticated;
    return (
        isAuthenticated
        ? <Component {...propsCopy} />
        : <Redirect to={{
            pathname: LOGIN_PATH,
            state: { from: this.props.location }
        }} />
    );
}
}

/**
 * Maps properties from Redux store to this component.
 * @param {Object} state Redux object
 * @return {Object} mapper properties
 */
function mapStateToProps(state) {
// pull out auth element from Redux store state
const { auth } = state;
// extract authenticated element from auth object
const { isAuthenticated } = auth;

return {
    isAuthenticated
}
}

export default connect(mapStateToProps)(PrivateRoute);

Компонент My Login, на который перенаправляется (упрощено для примера:

class LoginForm extends Component {

    constructor() {
        super();


        this.state = {
            email: '',
            password: '',
        }

        this.handleFormSubmit = this.handleFormSubmit.bind(this);


    }


    handleFormSubmit(event) {
        //event.preventDefault();

        const validation = this.validator.validate(this.state);
        this.setState({ validation });
        this.submitted = true;

        if (validation.isValid) {
            // submit form here
            this.props.loginUser({
                    email: this.state.email,
                    password: this.state.password
                });
        }
    }


    render() {

        return (

            // My login FROM code here
        )

    }
}

function mapStateToProps(state) {
    return {
        isFetching: state.auth.isFetching,
        loginError: state.auth.loginError,
        isAuthenticated: state.auth.isAuthenticated
    };
}

function mapDispatchToProps(dispatch, props, state) {
    return {
        loginUser: (credentials) => {
            dispatch(loginUser(credentials));
        },
    };
}

export default connect(mapStateToProps, mapDispatchToProps)(LoginForm);

Сейчас он работает там, где он перенаправляет на компонент LoginForm, если isAuthenticated имеет значение false. Я могу отправить форму входа в свою службу входа в систему и получить ответ об успехе и установить isAuthenticated.

У меня вопрос, как мне перенаправить на исходный маршрут? Где обычно выполняется перенаправление? Я предполагаю, что это никогда не делается в редукторе, поэтому это должно быть сделано в компоненте LoginForm, верно?

Я знаю, что множество ресурсов обсуждают весь этот процесс входа в систему, но я не могу найти тот, который занимается этой проблемой (что меня удивило). Каждый перенаправляет на определенную страницу ('/', '/ home' и т. Д.), Но как мне перехватить и перенаправить на исходный маршрут.

Ответы [ 2 ]

0 голосов
/ 30 августа 2018

@ Александр и @ bos570 Прежде всего я очень ценю то, как ты это сделал. Есть лучшие подходы к этому, но вот реализация для его построения контролируемым образом:

В вашем index.js:

import React from 'react';
import ReactDOM from 'react-dom';

import './styles.scss'; // it depends what styles you're using css,scss,jss
import App from './App';

ReactDOM.render(<App />, document.getElementById('app'));

В вашем App.js:

class App extends Component {

  state = {
    isAuthenticated: false,
  };

componentDidMount(){
//call authentication API here
// setState isAuthentication to true upon authentication success

}

render(){
return(
      <Provider store={store}>
        <BrowserRouter>{isAuthenticated ? <Routes /> : <Login />}</BrowserRouter>
      </Provider>
)}

Ваш Routes.js будет иметь все маршруты в Switch и будет отображать экран загрузки, если ответ API не даст успеха. и вы перенаправляете на страницу основного входа.

Даже если вы сделали разделение кода, он не будет загружать какие-либо пакеты из сети, кроме main.bundle.js в случае ошибки аутентификации. Я вижу людей, когда люди используют Redux как мастер на все руки в программировании. Я знаю, что ваша будущая реализация аутентификации даст вам refreshToken, это то, что API аутентификации делает для нас. Вы можете сохранить его в localStorage, и вы должны сделать это, если кто-то обновит браузер в любой момент, когда вы не сможете сохранить его в режиме редукции, так как мы знаем, что при обновлении браузера редукция потеряет состояние, поэтому здесь localStorage входит в играть. Используйте это с умом. Мне бы очень хотелось, чтобы с вами обоими было обращение, как мы можем сделать его лучше.

Надеюсь, это будет полезно для вас. и, возможно, будет использоваться избыточность для аутентификации. Я прекрасно провел время при реализации аутентификации в приложении. Ура

РЕДАКТИРОВАНИЕ сохраняйте все как есть. Но нам нужно знать, в какой момент вам нужно redux, localStorage, Context API

0 голосов
/ 30 августа 2018

Компонент PrivateRoute сохраняет предыдущий маршрут в from, когда происходит перенаправление из-за того, что isAuthenticated является false. Это можно использовать в LoginForm для перенаправления пользователя, когда isAuthenticated равно true. Просто извлеките from из this.props.location.state и используйте его в сочетании с Redirect компонентом из react-router-dom. Если вы войдете в систему this.props.location.state.from, вы увидите свойство pathname, содержащее путь маршрута строки, к которому пользователь попытался добраться в состоянии без проверки подлинности, который можно использовать для перенаправления их после успешной аутентификации.

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { Redirect, withRouter } from 'react-router-dom';

class LoginForm extends Component {
  constructor(props) {
    super(props);

    this.state = {
      email: '',
      password: '',
    }

    this.handleFormSubmit = this.handleFormSubmit.bind(this);
  }


  handleFormSubmit(event) {
    event.preventDefault();

    const validation = this.validator.validate(this.state);
    this.setState({ validation });
    this.submitted = true;

    if (validation.isValid) {
      // submit form here
      this.props.loginUser({
        email: this.state.email,
        password: this.state.password
      });
    }
  }


  render() {
    const { from } = this.props.location.state || { from: { pathname: "/" } };
    const { isAuthenticated } = this.props;

    if (isAuthenticated) {
      return <Redirect to={from} />;
    }

    return (
      {* login from code *}
    );
  }
}

function mapStateToProps(state) {
  return {
    isFetching: state.auth.isFetching,
    loginError: state.auth.loginError,
    isAuthenticated: state.auth.isAuthenticated
  };
}

function mapDispatchToProps(dispatch, props, state) {
  return {
    loginUser: (credentials) => {
      dispatch(loginUser(credentials));
    },
  };
}

export default withRouter(connect(mapStateToProps, mapDispatchToProps)(LoginForm));

Вам может потребоваться обновить ваш PrivateRoute компонент, чтобы убедиться, что он возвращает Route, это будет соответствовать react-router-dom пример :

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { Redirect, withRouter } from 'react-router-dom';

const PrivateRoute = ({ component: Component, ...rest }) => (
  <Route {...rest} render={props =>
    rest.isAuthenticated ? (
      <Component {...props} />
    ) : (
      <Redirect
        to={{
          pathname: LOGIN_PATH,
          state: { from: props.location }
        }}
      />
    )
  }
  />
);    

const mapStateToProps = ({ auth: { isAuthenticated } }) => ({ isAuthenticated });

export default withRouter(connect(mapStateToProps)(PrivateRoute));

Я создал упрощенный StackBlitz , демонстрирующий функциональность в действии.

Надеюсь, это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...