简体   繁体   中英

React issue with updating state during re-render

I have 2 components, a StaticComponent and an InteractiveComponent. The StaticComponent shows the user's information. It has a link to edit the information. That link has an onClick that fires off the handleEditClick function. This replaces the StaticComponent with an InteractiveComponent which has a form.

var StaticComponent = React.createClass({
  handleEditClick: function (event) {
    event.preventDefault();
    React.render(<InteractiveComponent user_info={this.props.user_info}  
                                       form_status={'form-to-be-sent'} />, 
                  document);
  },
})

The InteractiveComponent sets the state of the user_info from the props. It also assigns the state's formSubmissionStatus value to be 'form-to-be-sent' for the initial state, again from the props. The component also has a handleSubmit function and obviously the render function.

var InteractiveComponent = React.createClass({
  getInitialState: function() {
    return {
      user_info: JSON.parse(this.props.user_info),
      formSubmissionStatus: this.props.form_status
    };
  },

  handleSubmit: function(event, data) {
    // ...
  },

  render: function() {
    // ...
  }
});

The render function has a form that calls handleSubmit on submit. It also assigns a userInfo that will set the new props to be either the existing user_info data in the props, or the updated info from the state, depending on the submission status of the form.

The render function also renders either the form, if the status is set to 'form-to-be-sent', or it will render a StaticComponent otherwise. That's because it assumes the form was submitted.

render: function () {
  var profileForm = (
      <form ref="form" onSubmit={ this.handleSubmit }>
        <label>Your Name</label>
        <textarea id="user_name" defaultValue={this.state.user_info.name} ref='name' />
        <button className='greenbutton' type="submit">Update</button>
      </form>
    );

  var userInfo = this.state.formSubmissionStatus == 'form-to-be-sent' ? this.props.user_info : JSON.stringify(this.state.user_info);

  return (
    this.state.formSubmissionStatus == 'form-to-be-sent' ? profileForm : <StaticComponent user_info={userInfo} />
  );
}

The handleSubmit updates the user info in a new associative array, and does an ajax POST submission to the server. Before the ajax call, it updates the state of the user info to the latest data, and updates the formSubmissionStatus value.

handleSubmit: function(event, data) {
    event.preventDefault();

    var formData = $(this.refs.form.getDOMNode()).serialize(),
        latestUserInfo = JSON.parse(this.props.user_info),
        name = this.refs.name.getDOMNode().value.trim(),
        that = this;

    latestUserInfo['name'] = name;

    $.ajax({
      data: formData,
      dataType: "json",
      url: 'form-submit',
      type: "POST",
      beforeSend: function() {
        that.setState({
          user_info: latestUserInfo,
          formSubmissionStatus: 'form-already-submitted'
        });
      }
    });
  }

The problem is that the formSubmissionStatus value doesn't seem to be updated properly in the handleSubmit. I can click edit, fill in the form, press submit and see the new data update on the server, and the new info in a new StaticComponent. But I can't seem to be able to load the form up again by clicking on edit the second time. Using webdev tools, it seems as those the setState in the beforeSend callback isn't properly updating the formSubmissionStatus status.

The second time you click edit, and React renders an interactive component, it sees that there is already an existing InteractiveComponent there, so it reuses it by updating it's props and rerendering.

In your example, updating it's props and rerendering does nothing to change it's state. There is a component lifecycle method for componentWillReceiveProps that gives you an opportunity to transfer the new Props to the state.

So, try something like this on your interactiveComponent .

componentWillReceiveProps: function(nextProps) {
    this.setState({user_info: nextProps.user_info, formSubmissionStatus: nextProps.form_status});
}

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