我正在使用react-boilerplate构建React应用程序。我已经使用react- boilerplate生成器功能创建了身份验证容器,并将其与此公共api结合使用。通过电子邮件和密码后,它将返回令牌。
将令牌设置为浏览器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/>以获取更多信息。
<Redirect/>
// Render. render() { // Is Authenticated. if (this.props.isAuthenticated) return <Redirect to="/authpath"/> // Is Not Authenticated. // .. }