Mohammed Shirhaan
Mohammed Shirhaan

Reputation: 553

How to handle two setState methods to be executed one after other in ReactJS?

I have the following handleSubmit method, which sets the state and has a call back function to dispatch an action.

handleSubmit = event => {
    event.preventDefault();
    this.setState(
      {
        passenger: {
          ...this.state.passenger,
          flightNumber: this.props.match.params.flightNumber
        }
      },
      () =>
        this.props.dispatch(passengerActions.addPassenger(this.state.passenger))
    );

I want to set all the state properties to empty after dispatching the action. If I call setState again as follows in handleSubmit method above, I am getting some issues, mostly because of the Asynchronous behavior or setState.

  handleSubmit = event => {
    event.preventDefault();
    this.setState(
      {
        passenger: {
          ...this.state.passenger,
          flightNumber: this.props.match.params.flightNumber
        }
      },
      () =>
        this.props.dispatch(passengerActions.addPassenger(this.state.passenger))
    );
      this.setState(({ passenger }) => ({
        passenger: {
          ...passenger,
          flightNumber: "",
          firstName: "",
          lastName: "",
          address: "",
          dob: "",
          passportNumber: ""
        }
      }));
   };

I am new to ReactJS and JS. How can I handle this? Is there a way to pass another call back method? Or any other way?

Upvotes: 0

Views: 69

Answers (2)

T.J. Crowder
T.J. Crowder

Reputation: 1074038

First off, Jayce444's point is worth noting. The reason for setting state is to update what the component shows. You'll be showing the flight number very briefly before wiping the passenger information out entirely. So I'd either not bother with the first setState, or make the second one wait until the action has been completed (which means dispatch would need to return a promise or accept a callback). Waiting for the action to complete would also make sense for another reason: Actions can fail. Clearing the passenger information and then having the operation fail isn't likely to be ideal... :-)

But answering the question:

I want to set all the state properties to empty after dispatching the action.

In your attempt, you're calling setState immediately after having called setState, without waiting for the action to be dispatched. Instead, call setState within the previous setState's completion callback, after dispatching the action:

handleSubmit = event => {
  event.preventDefault();
  this.setState(
    {
      passenger: {
        ...this.state.passenger,
        flightNumber: this.props.match.params.flightNumber
      }
    },
    () => {
      this.props.dispatch(passengerActions.addPassenger(this.state.passenger))
      this.setState(({ passenger }) => ({
        passenger: {
          ...passenger,
          flightNumber: "",
          firstName: "",
          lastName: "",
          address: "",
          dob: "",
          passportNumber: ""
        }
      }));
    }
  );
};

If the dispatch can fail, be sure to only call setState to clear the fields on success.


Side note: If the goal of the second call is to clear all the passenger fields, you don't need to spread out the previous passenger object and you don't need the callback form of setState:

this.setState({
  passenger: {
    flightNumber: "",
    firstName: "",
    lastName: "",
    address: "",
    dob: "",
    passportNumber: ""
  }
});

Side note 2: Repeating field names like that is error-prone, You might want to use a class instead:

class Passenger {
    constructor() {
        this.flightNumber = "";
        this.firstName = "";
        this.lastName = "";
        this.address = "";
        this.dob = "";
        this.passportNumber = "";
    }
}

Then:

this.setState({passenger: new Passenger()});

Upvotes: 2

Smit Vora
Smit Vora

Reputation: 470

you can do something like :

this.setState({yourState},()=>{
     this.setState({againUpdateState});
});

Upvotes: 0

Related Questions