当前位置: 首页 > 知识库问答 >
问题:

React App登录错误:超出最大更新深度

葛承教
2023-03-14

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

登录之前工作正常,我已经添加了私人路由到一些需要身份验证的路由。

我得到的错误:

src/actions/authoctions.js

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
    };
  };

SRC/减速机/AuthReducers.js

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;
    }
}

App.js

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>
    );
  }
}

src/组件/login.js

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)

privaterout.js组件

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;

请帮我解决这个错误。

共有2个答案

万俟玉书
2023-03-14

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

privaterout.js组件

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;

src/actions/authoctions.js

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,
    }
}

SRC/减速机/AuthReducers.js

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;
    }
}

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

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

App.js

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);
贲绪
2023-03-14

我已通过替换PrivateRoute组件解决了我的错误,如下所示:

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);
 类似资料:
  • 问题内容: 我试图在ReactJS中切换组件的状态,但出现错误: 超过最大更新深度。当组件重复调用componentWillUpdate或componentDidUpdate内部的setState时,可能会发生这种情况。React限制了嵌套更新的数量,以防止无限循环。 我在代码中看不到无限循环,有人可以帮忙吗? ReactJS组件代码: 问题答案: 那是因为您在render方法中调用了toggle

  • 我在代码中没有看到无限循环,有人能帮忙吗? ReactJS组件代码:

  • 我正在用React做我的前几个实验,在这个组件中,我调用了一个外部API来获取所有NBA玩家的列表,通过作为组件道具接收的teamId过滤它们,最后呈现过滤玩家的标记。 一个需要考虑的问题是,由于我调用了API并获得了一个大列表,所以我将它保持在组件的状态,以便对该组件的新调用将使用该状态,而不是再次调用API。这不是生产代码,我没有API,所以我这样做是因为我收到了“太多请求”消息,因为我一直在

  • 我目前收到Maxiumum更新深度错误,不知道为什么。在我的代码中看不到无限循环。 "超过了最大更新深度。当组件在useEffect内部调用setState时,可能会发生这种情况,但useEffect要么没有依赖关系数组,要么其中一个依赖关系在每次渲染时都会发生变化。 此处显示错误 ReactJS组件代码: 下面的代码似乎有错误:超过了最大更新深度。当组件在useEffect中调用setState

  • 我在React中运行我的应用程序时收到一个错误。这个错误有很多问题,但我不知道如何解决它。当我按下链接时,它会指向登录组件。“http://localhost:3000/login” 这是我在网站上得到的错误: “已超出最大更新深度。当组件重复调用组件内部的 setState 时,可能会发生这种情况“组件将更新”或“组件更新”。React 限制了嵌套更新的数量,以防止无限循环。 这是我的登录页面:

  • 早上好,我正在开发一个React应用程序,通过REST API与后端通信。 该应用程序体系结构还使用 React 路由器,并使用服务器提供并存储在中的 JWT 令牌实现身份验证功能。 基本上: 用户连接到应用程序 如果用户未登录,则重定向到登录页面 登录后,它会重定向到带有路径的主页,其中应该显示带有路径的组件和带有路径的组件(如果一个很好地理解React路由器的工作) 在启动应用程序时,用户被正