Reactjs React应用程序登录错误:超过最大更新深度

Reactjs React应用程序登录错误:超过最大更新深度,reactjs,react-redux,react-router,Reactjs,React Redux,React Router,我正在使用react with redux构建带有后端passport jwt的登录身份验证系统 以前登录工作正常,我添加了一些需要身份验证的路由 我得到的错误: src/actions/authoctions.js src/reducers/authReducers.js App.js import React,{Component}来自'React'; 从“react Router dom”导入{BrowserRouter as Router,Route,Switch}; 从'react

我正在使用react with redux构建带有后端passport jwt的登录身份验证系统

以前登录工作正常,我添加了一些需要身份验证的路由

我得到的错误:

src/actions/authoctions.js

src/reducers/authReducers.js

App.js

import React,{Component}来自'React';
从“react Router dom”导入{BrowserRouter as Router,Route,Switch};
从'react redux'导入{Provider};
从“./store”导入存储;
从“./partials/Footer”导入页脚;
从“./partials/Header”导入标题;
从“./components/auth/Login”导入登录名;
从“/actions/authoctions”导入{setCurrentUser,logoutUser};
从“jwt解码”导入jwt_解码;
从“/utils/setAuthToken”导入setAuthToken;
从“/utils/PrivateRoute”导入PrivateRoute;
从“./components/user/Dashboard”导入仪表板;
从“./components/error/404”导入NotFound404;
if(localStorage.jwtToken){
setAuthToken(localStorage.jwtToken);
//解码令牌并获取用户信息和exp
const decoded=jwt_decode(localStorage.jwtToken);
存储调度(setCurrentUser(已解码));
//检查过期的令牌
const currentTime=Date.now()/1000;
if(decoded.exp
src/components/login.js

import React,{Component}来自“React”
从'react router dom'导入{Link};
从“类名称”导入类名称;
从'react redux'导入{connect};
从“../../actions/authActions”导入{loginUser};
从“属性类型”导入{PropTypes};
类登录扩展组件{
构造函数(){
超级();
这个州={
电子邮件:“”,
密码:“”,
错误:{}
}
this.handleChange=this.handleChange.bind(this);
this.handleSubmit=this.handleSubmit.bind(this);
}
手变(活动){
这是我的国家({
[event.target.name]:event.target.value
});
}
handleSubmit(事件){
event.preventDefault();
常量用户={
电子邮件:this.state.email,
密码:this.state.password
}
this.props.login用户(用户);
}
componentDidMount(){
if(this.props.auth.isAuthenticated){
this.props.history.push('/dashboard');
}
}
组件将接收道具(下一步){
if(nextrops.errors){
这是我的国家({
错误:nextrops.errors
});
}
if(nextrops.auth.isAuthenticated){
this.props.history.push('/dashboard');
}
}
渲染(){
const{errors}=this.state;
返回(
登录
电子邮件
{errors.email&({errors.email})}
密码
{errors.password&({errors.password})}
登录
还没有创建帐户吗?
忘记密码了?
)
}
}
const mapStateToProps=(state,ownProps)=>({
auth:state.auth,
错误:state.errors
})
const mapDispatchToProps={
登录用户
}
Login.propTypes={
auth:PropTypes.object.isRequired,
错误:PropTypes.object.isRequired,
登录用户:需要PropTypes.func.isRequired
}
导出默认连接(mapStateToProps、mapDispatchToProps)(登录)
privaterout.js组件

从“React”导入React;
从“react router dom”导入{Route,Redirect};
const PrivateRoute=({component:component,isAuthenticated,…rest})=>{
返回(
isAuthenticated==真
? 
: }
/>
)
}
导出默认私有路由;

请帮我解决这个错误

我建议您使用另一个状态变量来保存请求状态。如
logginging
如果为true,则显示加载如果为false和
isAuthenticated
为false,则不请求用户登录,也不登录。因此,将其重定向到
/login

privaterout.js组件

src/reducers/authReducers.js

请记住将登录作为privateRoute的道具

编辑:显示如何在App.js中使用

App.js

import React,{Component}来自'React';
从“react Router dom”导入{BrowserRouter as Router,Route,Switch};
从'react redux'导入{connect};
从“./partials/Footer”导入页脚;
从“./partials/Header”导入标题;
从“./components/auth/Login”导入登录名;
从“/actions/authoctions”导入{setCurrentUser,logoutUser};
从“jwt解码”导入jwt_解码;
从“/utils/setAuthToken”导入setAuthToken;
从“/utils/PrivateRoute”导入PrivateRoute;
从“./components/user/Dashboard”导入仪表板;
从“./components/error/404”导入NotFound404;
类应用程序扩展组件{
建造师(道具){
超级(道具);
const{dispatch}=props;
if(localStorage.jwtToken){
setAuthToken(localStorage.jwtToken);
//解码令牌并获取用户信息和exp
const decoded=jwt_decode(localStorage.jwtToken);
调度(setCurrentUser(已解码));
//检查
import { GET_ERRORS,CLEAR_ERRORS,SET_CURRENT_USER,LOGOUT_USER} from './types';
import axios from 'axios';
import setAuthToken from '../utils/setAuthToken';
import jwt_decode from 'jwt-decode';

export const loginUser= userdata =>dispatch=>{
    axios.post('/api/auth/login',userdata)
         .then(res=>{
             console.log('loginUser action response ==>',res.data);
             const {token}=res.data;
             localStorage.setItem('jwtToken',token);
             setAuthToken(token); 
             // Decode token to get user data
             const decoded = jwt_decode(token);
             dispatch(setCurrentUser(decoded));
         }).catch(err=>{
             dispatch({type:GET_ERRORS,payload:err.response.data});
         })
}

// Set logged in user
export const setCurrentUser = decoded => {
    return {
      type: SET_CURRENT_USER,
      payload: decoded
    };
  };
import isEmpty from '../validation/is-empty';
import { SET_CURRENT_USER,LOGIN_USER,LOGOUT_USER} from '../actions/types';

const initialState = {
    isAuthenticated: false,
    user: {}
  };

  export default function(state = initialState, action) {
    switch (action.type) {

        case LOGIN_USER:
        case SET_CURRENT_USER:
            return {
                ...state,
                isAuthenticated: !isEmpty(action.payload),
                user: action.payload
            };

        case LOGOUT_USER:
        return {
            ...state,
            isAuthenticated:false,
            user: {}
        };

        default:
        return state;
    }
}
import React, { Component } from 'react';
import {BrowserRouter as Router,Route,Switch} from 'react-router-dom';
import {Provider} from 'react-redux';
import store from './store';
import Footer from './partials/footer';
import Header from './partials/header';

import Login from './components/auth/login';
import { setCurrentUser ,logoutUser} from './actions/authActions';
import  jwt_decode  from 'jwt-decode';
import setAuthToken from './utils/setAuthToken';
import PrivateRoute from './utils/PrivateRoute';
import Dashboard from './components/user/dashboard';
import NotFound404 from './components/error/404';

if(localStorage.jwtToken){
  setAuthToken(localStorage.jwtToken);
  // Decode token and get user info and exp
  const decoded = jwt_decode(localStorage.jwtToken);
  store.dispatch(setCurrentUser(decoded));
    // Check for expired token
    const currentTime = Date.now() / 1000;
    if (decoded.exp < currentTime) {
      // Logout user
      store.dispatch(logoutUser());
      // Clear current Profile
      //store.dispatch(clearCurrentProfile());
      // Redirect to login
      window.location.href = '/login';
    }
}

export default class App extends Component {
  constructor(){
    super();
    this.state={
      isAuthenticated:store.getState().auth.isAuthenticated
    }
  }

  render() {
    return ( 
      <Provider store={store}>
      <Router>

      <div className="App">
        <Header/>
        <div className="container">
        <Switch>
        <Route exact path="/" component={Home}/>
        <Route exact path="/login" component={Login} />

        <PrivateRoute isAuthenticated={this.state.isAuthenticated} exact path="/dashboard" component={Dashboard}/>

        <Route component={NotFound404} />
        </Switch>
        </div>
        <Footer/>
      </div>

      </Router>
      </Provider>
    );
  }
}
import React, { Component } from 'react'
import { Link } from 'react-router-dom';
import classnames from 'classnames';
import { connect } from 'react-redux';
import { loginUser } from '../../actions/authActions';
import { PropTypes } from 'prop-types';

class Login extends Component {
    constructor(){
        super();
        this.state={
            email:'',
            password:'',
            errors:{}
        }
        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
        }
        this.props.loginUser(user);
    }


    componentDidMount() {
        if (this.props.auth.isAuthenticated) {
        this.props.history.push('/dashboard');
        }
    }

    componentWillReceiveProps(nextProps){

        if(nextProps.errors){
            this.setState({
                errors:nextProps.errors 
            });
        }

        if(nextProps.auth.isAuthenticated){
            this.props.history.push('/dashboard');
        }
    }

    render () {
        const {errors} = this.state;
        return (
            <div className="row my-5">
            <div className="col-md-4 offset-md-4 col-sm-12">
            <div className="card shadow-sm">
            <h5 className="card-header">Login</h5>
            <div className="card-body">
                <form onSubmit={this.handleSubmit}>
                    <div className="form-group">
                    <label htmlFor="email" className="label">Email</label>
                    <input type="email" id="email" name="email"  value={this.state.email} onChange={this.handleChange} className={classnames('form-control',{'is-invalid':errors.email})}/>
                    {errors.email && (<div className="invalid-feedback">{errors.email}</div>)}

                    </div>

                    <div className="form-group">
                    <label htmlFor="password" className="label">Password</label>
                    <input type="password" id="password" name="password"  value={this.state.password} onChange={this.handleChange}  className={classnames('form-control',{'is-invalid':errors.password})}/>
                    {errors.password && (<div className="invalid-feedback">{errors.password}</div>)}

                    </div>

                    <button type="submit" className="btn btn-success btn-block">Login</button>

                </form>
                <div className="py-3 border-bottom"></div>
                <Link to="/register" className="btn btn-default btn-block my-2">Haven't created account yet ?</Link>
                <Link to="/forgotpassword" className="btn btn-default btn-block">Forgot Password ?</Link>
            </div>
          </div>
            </div>
            </div>

        )
    }
}

const mapStateToProps = (state, ownProps) => ({
    auth:state.auth,
    errors:state.errors
})

const mapDispatchToProps = {
    loginUser
}

Login.propTypes={
    auth:PropTypes.object.isRequired,
    errors:PropTypes.object.isRequired, 
    loginUser:PropTypes.func.isRequired
}


export default connect(mapStateToProps,mapDispatchToProps)(Login)
import React from 'react';
import {Route,Redirect} from 'react-router-dom';

const PrivateRoute=({component: Component, isAuthenticated, ...rest}) => {
    return (
        <Route
          {...rest}
          render={(props) => isAuthenticated === true
            ? <Component {...props} />
            : <Redirect to={{pathname: '/login', state: {from: props.location}}} />}
        />
      )
}
export default PrivateRoute;
import React from 'react';
import {Route,Redirect} from 'react-router-dom';

class PrivateRoute extends Component {
render() {
    const {
        component: Component, loggingIn, isAuthenticated, ...rest
    } = this.props;
    if (loggingIn) {
        return (
            <div>
                Please wait.
            </div>
        );
    }
    return (<Route {...rest} render={props => (isAuthenticated ? (<Component {...props} />) : (<Redirect to={{ pathname: '/login', state: { from: props.location } }} />))} />);
}}
export default PrivateRoute;
import { GET_ERRORS,CLEAR_ERRORS,SET_CURRENT_USER,LOGOUT_USER} from './types';
import axios from 'axios';
import setAuthToken from '../utils/setAuthToken';
import jwt_decode from 'jwt-decode';

export const loginUser= userdata =>dispatch=>{
    dispatch(loggingIn(true));
    axios.post('/api/auth/login',userdata)
         .then(res=>{
             dispatch(loggingIn(false));
             console.log('loginUser action response ==>',res.data);
             const {token}=res.data;
             localStorage.setItem('jwtToken',token);
             setAuthToken(token); 
             // Decode token to get user data
             const decoded = jwt_decode(token);
             dispatch(setCurrentUser(decoded));
         }).catch(err=>{
             dispatch(loggingIn(false));
             dispatch({type:GET_ERRORS,payload:err.response.data});
         })
}

// Set logged in user
export const setCurrentUser = decoded => {
    return {
      type: SET_CURRENT_USER,
      payload: decoded
    };
  };

export const loggingIn = status => {
    return {
        type: 'LOGGINGIN',
        status,
    }
}
import isEmpty from '../validation/is-empty';
import { SET_CURRENT_USER,LOGIN_USER,LOGOUT_USER} from '../actions/types';

const initialState = {
    isAuthenticated: false,
    user: {}
  };

  export default function(state = initialState, action) {
    switch (action.type) {

        case LOGIN_USER:
        case SET_CURRENT_USER:
            return {
                ...state,
                isAuthenticated: !isEmpty(action.payload),
                user: action.payload
            };

        case LOGOUT_USER:
        return {
            ...state,
            isAuthenticated:false,
            user: {}
        };
        case 'LOGGINGIN':
            return {
                ...state,
                loggingIn: action.status,
            };
        default:
        return state;
    }
}
import React, { Component } from 'react';
import {BrowserRouter as Router,Route,Switch} from 'react-router-dom';
import {connect} from 'react-redux';
import Footer from './partials/footer';
import Header from './partials/header';

import Login from './components/auth/login';
import { setCurrentUser ,logoutUser} from './actions/authActions';
import  jwt_decode  from 'jwt-decode';
import setAuthToken from './utils/setAuthToken';
import PrivateRoute from './utils/PrivateRoute';
import Dashboard from './components/user/dashboard';
import NotFound404 from './components/error/404';


class App extends Component {
  constructor(props){
    super(props);
    const { dispatch } = props;
    if(localStorage.jwtToken){
        setAuthToken(localStorage.jwtToken);
        // Decode token and get user info and exp
        const decoded = jwt_decode(localStorage.jwtToken);
        dispatch(setCurrentUser(decoded));
        // Check for expired token
        const currentTime = Date.now() / 1000;
        if (decoded.exp < currentTime) {
           // Logout user
          dispatch(logoutUser());
          // Clear current Profile
          //dispatch(clearCurrentProfile());
          // Redirect to login
          window.location.href = '/login';
       }
    }
  }

  render() {
    const { isAuthenticated, loggingIn } = this.props;
    return ( 
      <Provider store={store}>
      <Router>

      <div className="App">
        <Header/>
        <div className="container">
        <Switch>
        <Route exact path="/" component={Home}/>
        <Route exact path="/login" component={Login} />

        <PrivateRoute loggingIn={loggingIn} isAuthenticated={isAuthenticated} exact path="/dashboard" component={Dashboard}/>

        <Route component={NotFound404} />
        </Switch>
        </div>
        <Footer/>
      </div>

      </Router>
      </Provider>
    );
  }
}
const mapStateToProps = state = {
   const { loggingIn, isAuthenticated } = state.auth;
   return { loggingIn, isAuthenticated }
}
export default connect(mapStateToProps)(App);
import React from 'react';
import { Route, Redirect } from 'react-router-dom';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';

const PrivateRoute = ({ component: Component,auth, ...rest }) => (
  <Route
    {...rest}
    render={props =>
      auth.isAuthenticated === true ? (
        <Component {...props} />
      ) : (
        <Redirect to="/login" />
      )
    }
  />
);

PrivateRoute.propTypes = {
  auth: PropTypes.object.isRequired
};

const mapStateToProps = state => ({
  auth: state.auth
});

export default connect(mapStateToProps)(PrivateRoute);