身份验证反应后重定向到其他页面

redirect to other page after authentication react

我正在使用 react-boilerplate 构建 React 应用程序。我已经使用 react-boilerplate 生成器功能创建了身份验证容器,并将其与 this public api 相结合。在我们通过电子邮件和密码后,它将 return 令牌。

设置token到浏览器localStorage后如何重定向到其他组件/页面?

感谢您的宝贵时间。

reducers.js

    import { fromJS } from 'immutable';
    import {
      CHANGE_EMAIL,CHANGE_PASSWORD,LOGIN_REQUEST, LOGIN_SUCCESS, LOGIN_FAILURE
    } from './constants';

    const initialState = fromJS({
        email: '',
        password: '',
        isFetching: false,
        isAuthenticated: false,
        errorMessage: '',
    });

    function loginReducer(state = initialState, action) {
      switch (action.type) {
        case CHANGE_EMAIL:
          return state
            .set('email', action.email);
        case CHANGE_PASSWORD:
          return state
            .set('password', action.password);
        case LOGIN_REQUEST:
          return state
              .set('isFetching', true)
              .set('isAuthenticated', false)
              .set('user', action.creds);
        case LOGIN_SUCCESS:
          return state
              .set('isFetching', false)
              .set('isAuthenticated', true)
              .set('errorMessage', '');
        case LOGIN_FAILURE:
          return state
              .set('isFetching', false)
              .set('isAuthenticated', false)
              .set('errorMessage', action.message);
        default:
          return state;
      }
    }

    export default loginReducer;

saga.js

import { call, put, select, takeLatest, takeEvery } from 'redux-saga/effects';
import { withRouter } from 'react-router-dom';
import { LOGIN_REQUEST } from './constants';
import { loginError, receiveLogin } from './actions';

import { postUserLogin } from './api';
import { makeSelectEmail, makeSelectPassword } from './selectors';

export function* loginUser() {



  const requestURL = 'https://reqres.in/api/login';

  try {

    const email = yield select(makeSelectEmail());
    const password = yield select(makeSelectPassword());
    const creds = {
        email: email,
        password: password,
    }

    // test post
    const headers = {
        method: 'POST',
        headers: {

            'Content-Type': 'application/json'
          },
        body: JSON.stringify({
            email: email,
            password: password,
         }),    
  };

    const users = yield call(postUserLogin,creds);

    const raw_token = JSON.stringify(users.token);
    const token_id = JSON.parse(raw_token);

    console.log("token_id : "+token_id);
    yield put(receiveLogin(token_id));
    localStorage.setItem('access_token', token_id);

  } catch (err) {
    console.log(err);
    let error;
    try {
      error = yield err.response.json();
    } catch (e) {
      error = { errors: [{ detail: `${err.name}: ${err.message}` }] };
    }


    yield put(loginError(error.error));
  }
}

// Individual exports for testing
export default function* defaultSaga() {
  // See example in containers/HomePage/saga.js

  yield takeEvery(LOGIN_REQUEST, loginUser);
}

index.js

import React from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { Helmet } from 'react-helmet';
import { FormattedMessage } from 'react-intl';
import { createStructuredSelector } from 'reselect';
import { compose } from 'redux';
import { Button, FormGroup, FormControl, ControlLabel, Col, PageHeader, HelpBlock } from "react-bootstrap";


import injectSaga from 'utils/injectSaga';
import injectReducer from 'utils/injectReducer';

import { makeSelectLogin,makeSelectEmail, makeSelectPassword, makeSelectErrorMessage, makeSelectIsAuthenticated } from './selectors';
import reducer from './reducer';
import saga from './saga';
import messages from './messages';


import { changeEmail, changePassword, requestLogin } from './actions';

export class Login extends React.Component { // eslint-disable-line react/prefer-stateless-function

  componentDidMount() {
    if ((this.props.email && this.props.email.trim().length > 0) && (this.props.password && this.props.password.length > 0) ) {
      this.props.onSubmitForm();
    }
  }

  renderErrorMessage(){

    if(this.props.errorMessage){
      return(
          <div className="info-red">
              {this.props.errorMessage}
          </div>
        );
    }

  }

  render() {
    return (
      <div>
        <Helmet>
          <title>Login</title>
          <meta name="description" content="Description of TestPage" />
        </Helmet>
            <div className="container-fluid">
                <div className="row">
                    <div className="col-md-6 col-md-offset-3">
                          <div className="login-form">
                              <form name="loginForm" onSubmit={this.props.onSubmitForm}>
                                <div className="form-group">
                                  <label htmlFor="email">Email address</label>
                                  <input type='email' 
                                          id="email" 
                                          className="form-control" 
                                          placeholder='Email Address' 
                                          required autoFocus 
                                          value={this.props.email} 
                                          onChange={this.props.onChangeEmail}/>
                                        <FormControl.Feedback />
                                    <HelpBlock>Email cannot be blank</HelpBlock>
                                  </div>
                                  <div className="form-group">
                                    <label htmlFor="password">Password</label>
                                  <input id="password" 
                                         type="password" 
                                        className="form-control" 
                                        placeholder="Password" 
                                        required
                                        value={this.props.password} 
                                        onChange={this.props.onChangePassword}/>
                                      <FormControl.Feedback />
                                  </div>
                                  <div className="form-group">
                                  <button type="submit" className="btn btn-primary">Submit</button>
                                  </div>
                              </form>
                              {this.renderErrorMessage()}
                          </div>
                    </div>
                </div>
            </div>
      </div>
    );
  }
}

Login.propTypes = {
  email: PropTypes.string,
  password: PropTypes.string,
  errorMessage: PropTypes.string,
  isAuthenticated: PropTypes.bool.isRequired,
  onChangeEmail: PropTypes.func,
  onChangePassword: PropTypes.func,
  onSubmitForm: PropTypes.func,
};

const mapStateToProps = createStructuredSelector({
  login: makeSelectLogin(),
  email: makeSelectEmail(),
  password: makeSelectPassword(),
  errorMessage: makeSelectErrorMessage(),
  isAuthenticated: makeSelectIsAuthenticated(),
});

function mapDispatchToProps(dispatch) {
  return {
    onChangeEmail: (evt) => dispatch(changeEmail(evt.target.value)),
    onChangePassword: (evt) => dispatch(changePassword(evt.target.value)),
    onSubmitForm: (evt) => {
      if (evt !== undefined && evt.preventDefault) evt.preventDefault();

      const creds = {
        email: email.value,
        password: password.value,
      }

      dispatch(requestLogin(creds));


    },
    fetchPost: (evt) => {
      dispatch(fetchPosts());
    },
  };
}

const withConnect = connect(mapStateToProps, mapDispatchToProps);

const withReducer = injectReducer({ key: 'login', reducer });
const withSaga = injectSaga({ key: 'login', saga });

export default compose(
  withReducer,
  withSaga,
  withConnect,
)(Login);

action.js

import {
  CHANGE_EMAIL,CHANGE_PASSWORD,LOGIN_REQUEST, LOGIN_SUCCESS, LOGIN_FAILURE
} from './constants';


export function changeEmail(email) {
  return {
    type: CHANGE_EMAIL,
    email,
  };
}


export function changePassword(password) {
  return {
    type: CHANGE_PASSWORD,
    password,
  };
}


export function requestLogin(creds) {

  return {
    type: LOGIN_REQUEST,
    isFetching: true,
    isAuthenticated: false,
    creds,
  };
}


export function receiveLogin(user_token) {
  return {
    type: LOGIN_SUCCESS,
    isFetching: false,
    isAuthenticated: true,
    token_id : user_token,
  };
}

export function loginError(message) {
  return {
    type: LOGIN_FAILURE,
    isFetching: false,
    isAuthenticated: false,
    message
  }
}

有关详细信息,请参阅 <Redirect/>

// Render.
render() {

  // Is Authenticated.
  if (this.props.isAuthenticated) return <Redirect to="/authpath"/>

  // Is Not Authenticated.
  // ..

}