0

Just can't think of a way to do this: I have a form and make an ajax request with the input upon submission, but how do I ensure that the state is completely set before I make the request? I know that setState is asynchronous and a version that accepts a callback exists, but I don't want to submit as soon as the state is set, rather when the user clicks the submit button. When I make the request, this.state is null still.

Any help or tips would be appreciated, thank you!

import React from 'react';

export default class Landing extends React.Component {
  constructor(props) {
    super(props);

    this.handleClick = this.handleClick.bind(this);
    this.handleChange = this.handleChange.bind(this);
    this.state = {
      question: ""
    };
  }

  handleClick(e) {
    const xhttp = new XMLHttpRequest();
    xhttp.onreadystatechange = function() {
      if (xhttp.readyState === XMLHttpRequest.DONE) {
        if (xhttp.status === 200) {
          console.log("success")
        } else {
          alert('There was a problem with the request.');
        }
      }
    };
    xhttp.open('POST', '/save', true);
    xhttp.setRequestHeader("Content-Type", "application/json");
    xhttp.send(JSON.stringify({ question: this.state.question }));
  }

  handleChange(e) {
    this.setState({ question: e.target.value });
  }

  render() {
    return (
      <div className="landing">
        <form onSubmit={this.handleClick}>
          <label>
            Question:
            <input type="text" value={this.state.question} onChange={this.handleChange} />
          </label>
          <input type="submit" value="Submit" />
        </form>    
      </div>
    );
  }
}

1 Answer 1

1

Did you try this?

  this.setState({
        state : newState
    },
    () => {
       // Call some method when state changes were done.
    });

Also you should use e.preventDefault(); as you are not submitting the for to any server.

  handleClick(e) {

   e.preventDefault();
    const xhttp = new XMLHttpRequest();
    xhttp.onreadystatechange = function() {
      if (xhttp.readyState === XMLHttpRequest.DONE) {
        if (xhttp.status === 200) {
          console.log("success")
        } else {
          alert('There was a problem with the request.');
        }
      }
    };
    xhttp.open('POST', '/save', true);
    xhttp.setRequestHeader("Content-Type", "application/json");
    xhttp.send(JSON.stringify({ question: this.state.question }));
  }
Sign up to request clarification or add additional context in comments.

5 Comments

Thanks for the tip! Is there any way to delay the method call until a button has been pressed/some action, instead of calling it as soon as the state finishes changing?
You are doing it right. In handleClick you should send ajax request and based on the response received set the state again with new data.
What do you mean "based on the response received set the state again with new data?" I send the value of this.state.question with the POST request, and I'm not expecting to update it afterwards.
Do you want to get notified of the response received? Whether your request was successful or not !
Yes, but the thing is I don't want to make the request until the state is finished setting, otherwise it would be sending wrong information. I think I found a workaround though by using a flag and delaying until it's true. Thank you!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.