简体   繁体   中英

React-bootstrap Alert is not Re-Rendering

I am working on login module. I am using nodeJs for my backend services.

Problem: I want to display a message whenever any error occurred duering login.

For this, i am sending a message to the client on every login request from the server.

  1. When client username and password is correct then server sends "OK" .

2.When password is incorrect then server sends "Password do not match!" .

  1. When email is incorrect then server sends "User is not in the database" .

React Code:

States

this.state={
            email:'',
            password:'',
            msg:''
        }

I have a Login component which renders all the input controls and button. In Login component i have a Submit button, input control for Email and Password .

When User clicks on Submit button then i am making a request to the server.

Login request:

 axios.post('http://localhost:4000/signin',{
            email:this.state.email,
            password:this.state.password
        })
        .then(response=>{
            if(response.data.msg==='OK'){
                window.location.href='/';
            }else{
                this.setState({
                    msg:response.data.msg
                })
                //alert(response.data.msg);
            }
        })
        .catch(err=>console.log(err));

Every thing is fine from the server. I am getting messages from the server on each success of failed login.

I am rendering a Message ( <Message show={true} msg={this.state.msg}/> ) component and passing show={true} and msg={this.state.msg} as props.

Message component

import React from 'react';
import 'bootstrap/dist/css/bootstrap.min.css';
import Alert from 'react-bootstrap/Alert';

export default class Message extends React.Component{
    constructor(props){
        super(props);
        this.state={
            show:false
        }
    }
      componentDidMount(){
        this.setState({show:this.props.show})
      }

    handleClose=()=>{
        this.setState({
            show:false
        })
    }
    render(){
        if(this.props.msg.length<4){
        return (<p></p>);
        }
           

        return(
            <div>
                <Alert variant='danger' show={this.state.show} onClose={this.handleClose} dismissible>
                    <Alert.Heading>Oh snap! You got an error!</Alert.Heading>
                    <p>
                        {this.props.msg}
                    </p>
                </Alert>
            </div>
        )
    }
}

All is i am returning a empty element when message length is less than 4. This ensures me that Message component will not render when we go to the login page initially or login is success.

Main problem:

I go to the login page and entered wrong email then i got this page.



问题图片



When i clicked on the close button inside the model, then it closes as expected. But, the problem is, when i again enter wrong username or password then i didn't get Alert .

Since the state of display is being passed by props, you only get to true when that component mounts, because you have the state change in the function componentDidMount and that will be executed just one time. For this you need to use the componentDidUpdate() function.

You should take in account that using componentDidUpdate is kind of tricky, since it will execute everytime the component updates, you can create an infinite loop with ease, this is why you must have a stop condition. Something like:

class MyComponent extends React.Component {
  constructor() {
    super();
    this.state = {
      show: false
    }
  }

  componentDidUpdate() {
    //Only update the state when the current value is different than the incoming value
    if(this.state.show != this.props.show) {
      this.setState({ show: this.props.show })
    }
  }

  ...
}

Update: Adding functional component version

For this case we can use the useEffect hook that will call an effect when any of the variables in the dependency array changes.

const MyFunctionalComponent = ({ show }) => { //destructuring show prop
  const [showAlert, setShowAlert] = useState(false); //our state variable  

  useEffect(() => {
    if(showAlert != show) { //only update when values are different
      setShowAlert(show); //update the state
    }
  }, [show]);

  ...
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM