javascript - Redux 和令牌认证:如何重定向用户
问题描述
我制作了自己的 Django rest Framework API,并包含了令牌身份验证。一切正常,我可以获得令牌和东西,但是,我在重定向我的用户时遇到了一些麻烦,使用:
this.props.push('/');
这是 UI 身份验证背后的逻辑:
import React, {Component} from 'react';
import { connect } from 'react-redux';
import {authLogin} from '../../actions/authentication.js';
class Login extends Component {
constructor(props){
super(props);
this.state = {
email: "",
password: ""
}
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(e){
this.setState({[e.target.name]: e.target.value});
}
handleSubmit(e){
e.preventDefault();
this.props.authLogin(this.state.email, this.state.password);
console.log(this.props.isAuthenticated);
console.log(this.props.loading);
if (this.props.isAuthenticated){
this.props.history.push('/');
}
}
render(){
return(
<div className="Login">
<h1> This is a form </h1>
<form>
<input type="text" onChange={this.handleChange} name="email"/>
<input type="password" onChange={this.handleChange} name="password"/>
<input type="submit" onClick={this.handleSubmit}/>
{ this.props.isAuthenticated &&
<p>Hello </p>
}
</form>
</div>
)
}
}
const mapStateToProps = state => {
console.log(state);
return {
token: state.authentication.token
}
}
export default connect(mapStateToProps, {authLogin})(Login);
此登录组件位于容器组件内,这是我希望 Redux 告诉“嘿,这是新令牌”的地方:
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import {connect } from 'react-redux';
import AppHeader from './header/AppHeader';
import HomePageStream from './HomePageStream/HomePageStream.js';
import HeaderCategories from './header/HeaderCategories.js';
import ArticleDetails from './ArticleDetails/ArticleDetails.js';
import { Route, Switch } from 'react-router-dom';
import { transitions, positions, Provider as AlertProvider } from 'react-alert'
import AlertTemplate from 'react-alert-template-basic'
import Alerts from './Alerts/Alerts.js';
import {authStateCheck} from '../actions/authentication.js';
import { Provider } from 'react-redux'
import { store } from '../store.js';
import { BrowserRouter } from "react-router-dom";
import Login from './Authentication/Login.js';
const options = {
timeout: 2000,
position: "top center"
}
class Container extends Component {
componentDidMount(){
this.props.authStateCheck();
}
render(){
return(
<div className="Container">
<Provider store={store}>
<AlertProvider template={AlertTemplate}
{...options}
>
<AppHeader />
<Alerts />
<HeaderCategories />
<Switch>
<Route exact
path="/:category"
render={routerProps => <HomePageStream {...routerProps}/>}
/>
<Route exact
path="/article/:slug"
render={routerProps => <ArticleDetails {...routerProps}/>}
/>
<Route exact
path="/authentication/login"
render={ routerProps => <Login {...routerProps}{...this.props}/>}
/>
</Switch>
</AlertProvider>
</Provider >
</div>
)
}
}
const mapStateToProps = state => {
console.log(state.authentication);
return {
isAuthenticated: state.authentication.token !== null,
loading: state.authentication.loading
}
}
export default connect(mapStateToProps, {authStateCheck} )(Container);
这是问题:当我点击提交时,isAuthenticated 是假的,因为我只在调用 handleSubmit() 之后才获得令牌!
这是我的操作的代码:
import axios from 'axios';
import {AUTH_START, AUTH_FAIL, AUTH_SUCESS, AUTH_LOGOUT} from './type';
export const authStart = () => {
return {
type: AUTH_START,
loading: true
};
}
export const authSucess = token => {
console.log(token);
return {
type: AUTH_SUCESS,
token: token,
error: null,
loading: false
};
}
export const authFail = error => {
console.log(error)
return {
token: null,
type: AUTH_FAIL,
error: error,
loading: false
};
}
export const logout = () => {
window.localStorage.removeItem('token');
window.localStorage.removeItem('expiration_time');
return {
type: AUTH_LOGOUT
}
}
export const checkAuthTimeOut = expiration_time => dispatch => {
return setTimeout(()=> {
dispatch(logout());
}, expiration_time * 1000);
}
export const authLogin = (email, password) => dispatch => {
dispatch(authStart());
console.log("I'm authlogin ! ");
axios.post('http://127.0.0.1:8000/rest-auth/login/',{
"email": email,
"password": password
})
.then( res => {
console.log("RESPONSE !")
const token = res.data.key
const expiration_time = new Date(new Date().getTime() + 3600 * 1000);
window.localStorage.setItem('token', token);
window.localStorage.setItem('expiration_time', expiration_time);
dispatch(authSucess(token));
console.log(token);
dispatch(checkAuthTimeOut(3600));
})
.catch( err => {
console.log(err);
dispatch(authFail());
})
}
export const authStateCheck = () => dispatch => {
const expiration_time = window.localStorage.getItem('expiration_time');
const token = window.localStorage.getItem('token');
if (!token){
return dispatch(logout());
} else if ( expiration_time <= new Date()){
console.log("EXPIRATION");
console.log( expiration_time <= new Date() )
return dispatch(logout());
} else {
console.log("NEW TIMER !!!! ");
return checkAuthTimeOut((expiration_time - new Date().getTime()) / 1000)
}
}
这是我的减速器:
import {AUTH_START, AUTH_FAIL, AUTH_SUCESS, AUTH_LOGOUT} from '../../actions/type';
const initialState = {
error: null,
token: null,
loading: false
}
export function authenticationReducer(state = initialState, action){
switch (action.type) {
case AUTH_START:
return {
...state,
loading: true
}
case AUTH_SUCESS:
console.log(action.token);
console.log(action.loading);
return {
...state,
error: null,
token: action.token,
loading: false
}
case AUTH_FAIL:
return {
...state,
error: action.error
}
default:
return state
}
}
但是,如果我再点击一次提交,它就会起作用。但我真的希望我的用户立即被重定向。我怎样才能解决这个问题 ??
非常感谢你;(
解决方案
我建议删除 history.push 代码并让 react-router 处理重定向:
import { Route, Redirect } from 'react-router'
...
<Switch>
<Route exact
path="/:category"
render={routerProps => <HomePageStream {...routerProps}/>}
/>
<Route exact
path="/article/:slug"
render={routerProps => <ArticleDetails {...routerProps}/>}
/>
<Route exact
path="/authentication/login"
render={ routerProps => (this.props.isAuthenticated ? (<Redirect to="/"/>) :(<Login {...routerProps}{...this.props}/>))}
/>
</Switch>
推荐阅读
- javascript - 按钮不会改变颜色
- python - 具有平均绝对误差成本函数 Python 的多项式回归
- sql - SQL Server:非聚集索引不起作用
- javascript - 无法将文本与 HTML 中的动画正确对齐
- arrays - 为什么合并排序更适合大型数组而快速排序更适合小型数组?
- ruby-on-rails - Rails:ActiveRecord 在同一模型上多次执行无意义的查询
- c# - C# 中的定时器 MinValue、MaxValue 和 Value
- swift - SwiftUI通过Navigationview推送视图在关闭工作表后弹出
- python - Pandas:如何识别 x 列中具有特定值的行,并将同一行中的其他值用作变量?
- r - 如何将ggplot2包装为R中的函数