在反应js中通过API获得响应后的表单重置问题

时间:2017-06-09 14:54:02

标签: forms reactjs

我通过redux API调用提交表单并获得响应但是在成功响应时我正在尝试重置表单但是给出了问题 -

setState(...): Cannot update during an existing state transition (such as within {渲染{1}}

这是我的文件 -

=========================

or another component's constructor). Render methods should be a pure function of props and state; constructor side-effects are an anti-pattern, but can be moved to 'componentWillMount'.

import React from 'react'; import DefaultLayout from '../Layout/DefaultLayout'; //import $ from 'jquery'; import { connect } from 'react-redux'; import { contactRequest } from '../actions/signupActions'; import { bindActionCreators } from 'redux'; import validator from 'validator'; class Contactus extends React.Component { constructor(props){ super(props); document.title = "Contact Us"; this.errorMapping = {"100": "Your message has been submitted.", "102": "Name cannot be empty.", "104": "Email cannot be empty.", "103": "Hotel cannot be empty.", "105": "Incorrect email format.", "106": "Phone cannot be empty."} this.state = {name: '',email:'',message :''}; this.handleInputChange = this.handleInputChange.bind(this); this.handleSubmit = this.handleSubmit.bind(this); this.baseState = this.state } handleInputChange(event) { this.setState({ [event.target.name]: event.target.value}); } handleSubmit(event) { event.preventDefault(); this.props.contactRequest(this.state); } render(){ const style_1 = {height: '240px'}; const style_2 = {marginRight: '15px'}; const style_3 = {width: 'auto'}; return( <DefaultLayout> <section id="content"> <div className="content-wrap"> <div className="container clearfix"> <div className="col-md-6 bottommargin"> <section id="google-map" className="gmap" style={style_1} ></section> </div> <div className="col-md-6"> <a href="#" data-toggle="modal" data-target="#contactFormModal" className="button button-3d nomargin btn-block button-xlarge hidden-xs center">Click here to Send an Email</a> <a href="#" data-toggle="modal" data-target="#contactFormModal" className="button button-3d nomargin btn-block visible-xs center">Send an Email</a> <div className="modal fade" id="contactFormModal" tabIndex="-1" role="dialog" aria-labelledby="contactFormModalLabel" aria-hidden="true"> <div className="modal-dialog"> <div className="modal-content"> <div className="modal-body"> <div className="contact-widget"> <div className="contact-form-result"> {this.props.resultMessage && this.props.resultMessage.status.map((msg, idx) => { if(msg === 100) { this.setState({name : "",email : ""}); return <span key={idx} id="succ_msg">{this.errorMapping[msg]}</span> } else { return <span key={idx} id="err_msg">{this.errorMapping[msg]}</span> } }) } </div> <form className="nobottommargin" id="r_contactform" name="r_contactform" method="post" onSubmit={this.handleSubmit} ref={(el) => this.myFormRef = el} > <div className="form-process"></div> <div className="col_half"> <label htmlFor="template-contactform-name">Name <small>*</small></label> <input type="text" id="template-contactform-name" name="name" value={this.state.name} className="sm-form-control required" onChange={this.handleInputChange} /> </div> <div className="col_half col_last"> <label htmlFor="template-contactform-email">Email <small>*</small></label> <input type="email" id="template-contactform-email" name="email" value={this.state.email} className="required email sm-form-control" onChange={this.handleInputChange} /> </div> <div className="clear"></div> <div className="clear"></div> <div className="col_half"> <label htmlFor="template-contactform-message">Message <small>*</small></label> <textarea className="required sm-form-control" id="template-contactform-message" name="message" value={this.state.message} rows="6" cols="30" onChange={this.handleInputChange}></textarea> <span className={this.state.messageError ? 'help-block error': '' }>{ this.state.messageError ? this.state.messageError: '' }</span> </div> <div className="col_full"> <button className="button button-3d nomargin" type="submit" id="contactform-submit" name="contactform-submit">Send Message</button> </div> </form> </div> </div> <div className="modal-footer"> <button type="button" className="btn btn-default" data-dismiss="modal">Close</button> </div> </div> </div> </div> </div> </div> </div> </section> </DefaultLayout> ); } } function mapStateToProps(state){ console.log("View data :"+JSON.stringify(state.Contactdata)); return { resultMessage: state.Contactdata } } function mapDispatchToProps(dispatch) { return bindActionCreators({contactRequest: contactRequest}, dispatch) } export default connect(mapStateToProps, mapDispatchToProps) (Contactus); 函数中获取响应并尝试更新已应用条件mapStateToProps的状态。

请让我知道我做错了什么。

谢谢

2 个答案:

答案 0 :(得分:1)

这就是你在setState方法中执行render的原因:

{this.props.resultMessage && this.props.resultMessage.status.map((msg, idx) => { 
      if(msg === 100) { 
         this.setState({name : "",email : ""});
         .....

msg == 100 为真时,您正在setState,再次触发re-rendering,再次setState ...... 。无限循环

删除setState它将起作用。

使用 componentWillReceiveProps 生命周期方法,并在其中执行setState

componentWillReceiveProps(newProps) {
    newProps.resultMessage.status.forEach((msg, idx) => { 
         if(msg === 100) { 
              this.setState({
                  name : "",
                  email : ""
              });
         }
    }           
}

答案 1 :(得分:1)

setState的正确位置不在map函数中,因为你从redux接收道具,你可以在componentWillReceiveProps函数中做到这一点

class Contactus extends React.Component {
    constructor(props){
        super(props);
        document.title = "Contact Us";

        this.errorMapping = {"100": "Your message has been submitted.",
        "102": "Name cannot be empty.",
        "104": "Email cannot be empty.",
        "103": "Hotel cannot be empty.",
        "105": "Incorrect email format.",
        "106": "Phone cannot be empty."}

        this.state = {name: '',email:'',message :''};

        this.handleInputChange = this.handleInputChange.bind(this); 
        this.handleSubmit = this.handleSubmit.bind(this); 

        this.baseState = this.state 
    }
    componentWillReceiveProps(nextProps) {
           nextProps.resultMessage.status.forEach((msg, idx) => { 
                if(msg === 100) { 
                    this.setState({name : "",email : ""});
                 }
          }           
    }

    handleInputChange(event) {
        this.setState({ [event.target.name]: event.target.value});
    }

    handleSubmit(event) {
        event.preventDefault();
        this.props.contactRequest(this.state);
    }


    render(){
        const style_1 = {height: '240px'};
        const style_2 = {marginRight: '15px'};
        const style_3 = {width: 'auto'};

        return(
            <DefaultLayout>
                <section id="content">
                    <div className="content-wrap">
                        <div className="container clearfix">

                            <div className="col-md-6 bottommargin">
                                <section id="google-map" className="gmap" style={style_1} ></section>
                            </div>

                            <div className="col-md-6">

                                <a href="#" data-toggle="modal" data-target="#contactFormModal" className="button button-3d nomargin btn-block button-xlarge hidden-xs center">Click here to Send an Email</a>
                                <a href="#" data-toggle="modal" data-target="#contactFormModal" className="button button-3d nomargin btn-block visible-xs center">Send an Email</a>

                                <div className="modal fade" id="contactFormModal" tabIndex="-1" role="dialog" aria-labelledby="contactFormModalLabel" aria-hidden="true">
                                    <div className="modal-dialog">
                                        <div className="modal-content">

                                            <div className="modal-body">

                                                <div className="contact-widget">
                                                        <div className="contact-form-result">
                                                            {this.props.resultMessage && this.props.resultMessage.status.map((msg, idx) => { 
                                                                     if(msg === 100) { 

                                                                        return <span key={idx} id="succ_msg">{this.errorMapping[msg]}</span>
                                                                     } else {
                                                                        return <span key={idx} id="err_msg">{this.errorMapping[msg]}</span>
                                                                    }
                                                                })
                                                            }
                                                        </div>
                                                    <form className="nobottommargin" id="r_contactform" name="r_contactform" method="post" onSubmit={this.handleSubmit} ref={(el) => this.myFormRef = el} >

                                                        <div className="form-process"></div>

                                                        <div className="col_half">
                                                            <label htmlFor="template-contactform-name">Name <small>*</small></label>
                                                            <input type="text" id="template-contactform-name" name="name" value={this.state.name} className="sm-form-control required" onChange={this.handleInputChange} />
                                                        </div>

                                                        <div className="col_half col_last">
                                                            <label htmlFor="template-contactform-email">Email <small>*</small></label>
                                                            <input type="email" id="template-contactform-email" name="email" value={this.state.email} className="required email sm-form-control" onChange={this.handleInputChange} />
                                                        </div>

                                                        <div className="clear"></div>


                                                        <div className="clear"></div>

                                                        <div className="col_half">
                                                            <label htmlFor="template-contactform-message">Message <small>*</small></label>
                                                            <textarea className="required sm-form-control" id="template-contactform-message" name="message"  value={this.state.message} rows="6" cols="30" onChange={this.handleInputChange}></textarea>
                                                            <span className={this.state.messageError ? 'help-block error': '' }>{ this.state.messageError ? this.state.messageError: '' }</span>
                                                        </div>

                                                        <div className="col_full">
                                                            <button className="button button-3d nomargin" type="submit" id="contactform-submit" name="contactform-submit">Send Message</button>
                                                        </div>

                                                    </form>

                                                </div>


                                            </div>
                                            <div className="modal-footer">
                                                <button type="button" className="btn btn-default" data-dismiss="modal">Close</button>
                                            </div>
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>

                    </div>
                </section>

            </DefaultLayout>
        );  
    }
}