Qli
Qli

Reputation: 189

React js, Maximum update depth exceeded

I'm facing an error:

Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.

My code is:

class Login extends React.Component {
  constructor(props){
    super(props);
    this.state = {
      firstName: '',
      password: '',
      isLogged: false
    }
    this.handleSubmit = this.handleSubmit.bind(this);
    this.handleChangeFirstName = this.handleChangeFirstName.bind(this);
    this.handleChangePassword = this.handleChangePassword.bind(this);
  }

  handleChangeFirstName(event) {
    this.setState({firstName: event.target.value})
  }
  handleChangePassword(event) {
    this.setState({password: event.target.value})
  }

  handleSubmit(event) {
    console.log('login');
    console.log('first name:' ,this.state.firstName);
    console.log('password:' ,this.state.password);
    this.props.loginRequest(this.state.firstName, this.state.password);
    // console.log('login',this.props)
  }

  componentDidUpdate() {
    if(this.props.request.message === 'ok'){
      console.log('ok');
      this.setState({isLogged: true});
      this.props.history.push('/');
      //path is ok!!!
      console.log('path from history: ', this.props.history);
    }
  }

  render() {
    return(
      <div>
        {this.state.isLogged ? <App />
         :
        <div className="container">
          <div className="row">
            <div className="col-sm-5 log-style">
              <div className="log-title">
                <h2>Admin Login</h2>
                <p>Please enter you login details</p>
              </div>
              <div className="row p-2">
                <input 
                  type="text" 
                  id="fname" 
                  onChange={this.handleChangeFirstName}
                  className="form-control input-sm"
                  placeholder="First name" 
                  style={{'border':'none'}} required/>
              </div>
              <div className="row p-2">
                <input 
                  type="password"
                  id="pass"
                  onChange={this.handleChangePassword}
                  className="form-control input-sm"
                  placeholder="Password" 
                  style={{'border':'none'}} required/>
              </div>
              <div className="row" style={{'marginTop':'40px'}}>
                <div className="col-sm-6" style={{'padding': '2px'}}>
                  <input type="checkbox" 
                    style={{
                     'float': 'left',
                     'marginTop': '10px',
                     'marginLeft': '13px'
                    }} />
                   <label 
                     style={{
                      'marginTop': '7px',
                      'marginLeft': '9px'
                   }}>Remember me </label>
                </div>
                <div className="col-sm-6" 
                  style={{
                   'paddingTop': '7px',
                   'textAlign': 'right'
                  }}>
                  <a href="#" 
                    style={{
                     'color': 'purple', 
                     'fontSize': '13px'
                    }}>
                    Forgot password?</a>
                </div>
              </div>

              <div className="row" style={{'justifyContent': 'center'}}>
                <div className="btn btn-sm borderBtn" 
                  style={{
                   'backgroundColor':'purple'}}
                    onClick={() => this.handleSubmit(event)}>
                  <span className="fi-account-login">Login</span>
                </div>
              </div>
            </div>
          </div>
        </div>
       }  
       </div>
    )
  }
}


const mapStateToProps = state => (
  { user: state.userReducer.user, request: state.userReducer.request }
);

const mapDispatchToProps = dispatch => 
  bindActionCreators({loginRequest}, dispatch);


export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Login));

I have another component which uses Router to switch pages, and a mail component in which includes Login page.

Upvotes: 5

Views: 34628

Answers (1)

Peter Van Drunen
Peter Van Drunen

Reputation: 553

The problem is every time you component updates, you are updating it again without any kind of break condition. This creates an infinite loop. You should check that this.state.isLogged is NOT true before updating it here:

componentDidUpdate() {
  if(this.props.request.message === 'ok'){
      console.log('ok');
      if (!this.state.isLogged) {
          this.setState({
              isLogged: true
          });
      }
      this.props.history.push('/');
      //path is ok!!!
      console.log('path from history: ', this.props.history);
  }
}

This prevents updating the isLogged state when it's already true.

Upvotes: 10

Related Questions