SrikanthPailla
SrikanthPailla

Reputation: 33

React js componentDidUpdate not called when state changed

Hi I am a beginner in React and trying to build my first app

login.js

import React from 'react'
import LoginForm from './loginForm'
import SignUpForm from './signUpForm'
import Home from './home'

class LoginPopUp extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            signup: false,
            login: true,
            loginSuccess: false,
        }
        this.renderLogin = this.renderLogin.bind(this)
        this.renderSignUp = this.renderSignUp.bind(this)
        this.uponSuccessfulLogin = this.uponSuccessfulLogin.bind(this)
    }

    renderSignUp() {
        this.setState({signup: true, login: false})
    }

    renderLogin() {
        this.setState({signup: false, login: true})
    }

    uponSuccessfulLogin() {
        this.setState({loginSuccess: true})
    }

    render() {
        if (this.state.signup) {
            return <SignUpForm renderLogin={this.renderLogin}/>
        } else if (this.state.login) {
            return <LoginForm renderSignUp={this.renderSignUp} uponSuccessfulLogin={this.uponSuccessfulLogin}/>
        } else if (this.state.loginSuccess) {
            return <Home/>
        }
    }
}

export default LoginPopUp;

loginForm.js

import React from 'react'
import { post } from 'axios';

class LoginForm extends React.Component {

    constructor(props) {
      super(props);
      this.state ={
        username: '',
        password: '',
        loginSuccess: '',
        submit: false,
      }
      this.onUsernameChange = this.onUsernameChange.bind(this)
      this.onPasswordChange = this.onPasswordChange.bind(this)
      this.onLoginSubmitButton = this.onLoginSubmitButton.bind(this)
      this.authenticate = this.authenticate.bind(this)
      this.handleButtonClick = this.handleButtonClick.bind(this)
    }

    onUsernameChange(e) {
        this.setState({username: e.target.value})
    }

    onPasswordChange(e) {
        this.setState({password: e.target.value})
    }

    componentDidUpdate() {
        if (this.state.loginSuccess) {
            if (this.state.loginSuccess === 200) {
                this.props.uponSuccessfulLogin()
            } else {
                alert("Authentication Failed! Provide valid credentials.")
            }
        }
    }

    authenticate() {
        const url = 'http://127.0.0.1:8000/api-token-auth/';
        const formData = new FormData();
        formData.append('username', this.state.username);
        formData.append('password', this.state.password);
        const config = {
            headers: {
                'content-type': 'multipart/form-data'
            }
        }
        post(url, formData, config)
          .then(response => response.status)
          .then(status => this.setState({loginSuccess: status}))
    }

    onLoginSubmitButton() {
        this.authenticate()
    }

    handleButtonClick() {
        this.props.renderSignUp()
    }

    render() {
        if (!this.state.loginSuccess){
            return (
                <div>
                    <h1>Login</h1>
                    <form className='LoginForm' onSubmit={this.onLoginSubmitButton}>
                        <label>
                            Username:
                            <input onChange={this.onUsernameChange}/>
                        </label>
                        <br/>
                        <label>
                            Password:
                            <input type='password' onChange={this.onPasswordChange}/>
                        </label>
                        <br/>
                        <input type='submit' value='Submit'></input> 
                    </form>
                    <br/><br/><br/>
                    <span>Not a member? </span>
                    <button id="clickHere" onClick={this.handleButtonClick}>
                        Click here to SignUp
                    </button>
                </div>
            );
        }
    }
}

export default LoginForm;

When post (.then(status => this.setState({loginSuccess: status}))** ) is successful I expect componentDidUpdate is called and <Home/> is rendered but here it doesn't render <Home/> instead I get same login page. Please help me understand what did I do wrong.**

Upvotes: 1

Views: 533

Answers (5)

MUHAMMAD ILYAS
MUHAMMAD ILYAS

Reputation: 1450

Working example using https://jsonplaceholder.typicode.com/posts

and check the status for 201 (created) to complete the test example

you must have to prevent default events

  onLoginSubmitButton(e) {
    e.preventDefault();
    this.authenticate();
  }

https://codesandbox.io/s/compassionate-leavitt-ctil9

Upvotes: 0

Nithish
Nithish

Reputation: 5999

The issue is because in componentDidUpdate you are calling this.props.uponSuccessfulLogin() where only loginSuccess is getting updated but login is still true. Hence even though you provided valid credentials even after getting 200 you are still seeing Login Page.

Make below changes to the parent component method uponSuccessfulLogin

uponSuccessfulLogin() {
   this.setState(() => ({loginSuccess: true, signup: false, login: false}))
}

By doing so, since signup and login will be set to false and then Home component will be visible.

Also in your loginForm.js component, return null if you doesn't want to render anything.

authenticate(e) {
   e.preventDefault();
   //..rest of the code
}

onLoginSubmitButton(e) {
   this.authenticate(e);
}

render() {
        if (!this.state.loginSuccess){
            //..rest of your code for displaying Login form
        } else return null;
    }

Hope this helps.

Upvotes: 0

Yousaf
Yousaf

Reputation: 29282

you need to call Event.preventDefault() function to prevent page from reloading when form is submitted

onLoginSubmitButton(event) {
    event.preventDefault();
    this.authenticate();
}

Event.preventDefault() will disable the default behaviour of the browser when form is submitted.

Upvotes: 2

adel
adel

Reputation: 3507

try this in loginForm when updating login success :

this.setState(currentState=>({...currentState, loginSuccess:status))

Upvotes: 0

Hagai Harari
Hagai Harari

Reputation: 2877

you need to set both signup and login to false in uponSuccessfulLogin in order for your code to reach last else if case

 uponSuccessfulLogin() {
        this.setState({loginSuccess: true, signup: false, login: false})
    } 

Upvotes: 0

Related Questions