React setState doesn't change state even when I use react update add on

After reading about React, I decided to test some simple ideas in a sample project. But I wondered why setState

it didn't work as expected. setState

does not change state even when I use the update add-in. When I change setState

to state, it works! I also registered a new state object and that's correct. I do not know what is wrong! I would appreciate your help.

import React from 'react';
import update from 'react-addons-update';
class WebFooterSubscription extends React.Component {
    //========================================================
    constructor(props) {
        super(props);
        this.state = {
            formIsValid: false,
            email: {
                value: "",
                focused: false,
                touched: false,
                isValid: false,
                error: "Enter your email"
            },
            mobile: {
                value: "",
                focused: false,
                touched: false,
                isValid: false,
                error: "Enter your mobile"
            }
        };
    }
    //=================================================================
    componentDidUpdate(prevProps, prevState) {}
    //========================================================
    onBlur(event) {
        if ('mobile1' === event.target.id) {
            let newState = { ...this.state,
                mobile: { ...this.state.mobile,
                    value: event.target.value,
                    focused: false,
                    touched: true
                }
            };
            console.log("mobile blur:", JSON.stringify(newState));
            this.setState(newState); // this seems not to work!
        }
        if ('email1' === event.target.id) {
            let newState = update(this.state, {
                email: {
                    value: {
                        $set: event.target.value
                    },
                    touched: {
                        $set: true
                    },
                    focused: {
                        $set: false
                    }
                }
            });
            console.log("email blur:", JSON.stringify(newState));
            this.setState(newState); // this seems not to work!
        }
        this.cmdValidate();
    }
    //========================================================
    onFocus(event) {
        console.log("focus occured");
        if ('mobile1' === event.target.id) {
            let newState = { ...this.state.mobile
            };
            newState.focused = true;
            newState.touched = true;
            this.setState({ ...this.state,
                mobile: newState
            });
        }
        if ('email1' === event.target.id) {
            this.setState({ ...this.state,
                email: { ...this.state.email,
                    touched: true,
                    focused: true
                }
            });
        }
    }
    //========================================================
    cmdValidate() {
        // console.log("length " ,this.state.mobile.value.length);
        if (this.state.mobile.value && this.state.mobile.value.length === 11) {
            this.setState({ ...this.state,
                mobile: { ...this.state.mobile,
                    isValid: true,
                    error: ""
                }
            });
        } else {
            this.setState({ ...this.state,
                mobile: { ...this.state.mobile,
                    isValid: false,
                    error: "Enter your cell phone number correctly"
                }
            });
        }
        if (this.state.email.value) {
            let isValidEmail = true;
            if (isValidEmail) {
                this.setState({ ...this.state,
                    email: { ...this.state.email,
                        isValid: isValidEmail
                    }
                });
            } else {
                this.setState({ ...this.state,
                    email: { ...this.state.email,
                        isValid: false,
                        error: "Your email is not correct"
                    }
                });
            }
        } else {
            this.setState({ ...this.state,
                email: { ...this.state.email,
                    isValid: false,
                    error: "Enter email"
                }
            });
        }
        if (this.state.email.isValid && this.state.mobile.isValid) {
            this.setState({ ...this.state,
                formIsValid: true
            });
        } else {
            this.setState({ ...this.state,
                formIsValid: false
            });
        }
    }
    //========================================================
    onSubmitClick(event) {
        //this.setState({count : this.state.count + 1});
        event.preventDefault();
    }
    render() {
        return (<form name="subscriptionForm" id="subscriptionForm" className="form" method="post">
                                <div className={`form-group ${this.state.email.touched && !this.state.email.isValid ? ' has-danger' : ''}`}>
                                    <div className="col-md-12  ">
                                        <div className="input-group" >
                                            <input id="email1" name="email1" onBlur={(event)=>this.onBlur(event)} onFocus={(event)=>this.onFocus(event)}  className="form-control"  placeholder="email"  type="text" />
                                            <div className="input-group-addon"><img src="assets/images/icons/svg/opened-email-envelope.svg" alt="email" width="24px" height="24px" /></div>
                                        </div>
                                        <div className="help-block" hidden={!this.state.email.focused}>
                                                 {this.state.email.touched && ((this.state.email.error && <span>{this.state.email.error}</span>))}
                                        </div>

                                    </div>
                                </div>
                                <div className={`form-group ${this.state.mobile.touched && !this.state.mobile.isValid ? ' has-danger' : ''}`}>
                                    <div className="col-md-12  ">
                                        <div className="input-group" >
                                            <input id="mobile1" name="mobile1" className="form-control" onBlur={(event)=>this.onBlur(event)}  onFocus={(event)=>this.onFocus(event)}   placeholder="cell phone" type="text" />
                                            <div className="input-group-addon"><img src="assets/images/icons/svg/talking2.svg" alt="cell phone" width="24px" height="24px" /></div>
                                        </div>
                                    </div>
                                </div>
                                <div className="leftButton">
                                    <button type="submit"  onClick={(event)=> this.onSubmitClick(event)}  className="btn btn-primary" >Subscribe</button>
                                </div>
                                    <div>
                                        {JSON.stringify(this.state)}disabled={!this.state.formIsValid}
                                    </div>
                            </form>);
    }
}
export default WebFooterSubscription;

      

+3


source to share


2 answers


  • setState is an async operation, so sometimes when you try to access a new state immediately after setting it, you don't get the updated state.
  • So, to access the new state immediately after setting it, you need to access it via a callback function that looks like this: -

    this.setState ({// here you provide a new state }, () => {// , here you refer to it )

  • In your case, you can access it this way in the onBlur function.



  onBlur(event){
let newState
        if('mobile1'===event.target.id){
            newState= {...this.state,mobile:{...this.state.mobile ,value:event.target.value, focused:false, touched:true}};
            console.log("mobile blur:" ,JSON.stringify(newState));
         
        }
        if('email1'===event.target.id){
             newState = update(this.state, { email: { value: {$set: event.target.value} ,touched: {$set: true},focused:{$set:false}}   });
            console.log("email blur:" ,JSON.stringify(newState));
        }
        this.setState(newState,()=>{this.cmdValidate()})
        
    }
      

Run codeHide result


  • Hope the above solutions can solve your problem ..... :)
+1


source


I assume this is because setState is isync and you register it right after. It will update when the render is called.



0


source







All Articles