React的setState在使用react-update添加-on时即使不改变状态,也没有改变状态

3

在阅读完React相关资料后,我决定在一个示例项目中测试一些简单的想法。但是我很惊讶为什么setState没有按预期工作。setState没有改变状态,即使我正在使用更新插件。当我将setState更改为state时,它可以工作!我也记录了新的状态对象,并且它是正确的。我不知道哪里出了问题!感谢您的帮助。

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;

可能是为什么调用setState方法不会立即改变状态?的重复问题。 - Mayank Shukla
2个回答

1
  • setState是一个异步操作,所以有时当您尝试在设置新状态之后立即访问它时,您不会得到更新的状态。
  • 因此,为了在设置新状态后立即访问新状态,您需要通过回调函数进行访问,它看起来像这样:

    this.setState({//在此处提供新状态},()=>{//在此处访问它})

  • 在您的情况下,您可以通过onBlur函数以这种方式访问它。

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

  • 希望上述解决方案能够解决您的问题..... :)

谢谢你,Rajat。我知道setState是异步的,但我没有使用日志记录。我已经使用了JSON.Stringify来显示渲染方法中的整个状态。它最终必须在渲染方法中显示状态更新。 - Behdad

0
我猜测这是因为setState是异步的,而你在立即记录它。在调用render时,它将被更新。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接