React.js, wait for setState to finish before triggering a function?

前端 未结 5 710
庸人自扰
庸人自扰 2020-12-23 08:31

Here\'s my situation:

  • on this.handleFormSubmit() I am executing this.setState()
  • inside this.handleFormSubmit(), I am calling this.findRoutes(); - whic
相关标签:
5条回答
  • 2020-12-23 09:22

    Why not one more answer? setState() and the setState()-triggered render() have both completed executing when you call componentDidMount() (the first time render() is executed) and/or componentDidUpdate() (any time after render() is executed). (Links are to ReactJS.org docs.)

    Example with componentDidUpdate()

    Caller, set reference and set state...

    <Cmp ref={(inst) => {this.parent=inst}}>;
    this.parent.setState({'data':'hello!'});
    

    Render parent...

    componentDidMount() {           // componentDidMount() gets called after first state set
        console.log(this.state.data);   // output: "hello!"
    }
    componentDidUpdate() {          // componentDidUpdate() gets called after all other states set
        console.log(this.state.data);   // output: "hello!"
    }
    

    Example with componentDidMount()

    Caller, set reference and set state...

    <Cmp ref={(inst) => {this.parent=inst}}>
    this.parent.setState({'data':'hello!'});
    

    Render parent...

    render() {              // render() gets called anytime setState() is called
        return (
            <ChildComponent
                state={this.state}
            />
        );
    }
    

    After parent rerenders child, see state in componentDidUpdate().

    componentDidMount() {           // componentDidMount() gets called anytime setState()/render() finish
    console.log(this.props.state.data); // output: "hello!"
    }
    
    0 讨论(0)
  • 2020-12-23 09:23

    setState() has an optional callback parameter that you can use for this. You only need to change your code slightly, to this:

    // Form Input
    this.setState(
      {
        originId: input.originId,
        destinationId: input.destinationId,
        radius: input.radius,
        search: input.search
      },
      this.findRoutes         // here is where you put the callback
    );
    

    Notice the call to findRoutes is now inside the setState() call, as the second parameter.
    Without () because you are passing the function.

    0 讨论(0)
  • 2020-12-23 09:25

    According to the docs of setState() the new state might not get reflected in the callback function findRoutes(). Here is the extract from React docs:

    setState() does not immediately mutate this.state but creates a pending state transition. Accessing this.state after calling this method can potentially return the existing value.

    There is no guarantee of synchronous operation of calls to setState and calls may be batched for performance gains.

    So here is what I propose you should do. You should pass the new states input in the callback function findRoutes().

    handleFormSubmit: function(input){
        // Form Input
        this.setState({
            originId: input.originId,
            destinationId: input.destinationId,
            radius: input.radius,
            search: input.search
        });
        this.findRoutes(input);    // Pass the input here
    }
    

    The findRoutes() function should be defined like this:

    findRoutes: function(me = this.state) {    // This will accept the input if passed otherwise use this.state
        if (!me.originId || !me.destinationId) {
            alert("findRoutes!");
            return;
        }
        var p1 = new Promise(function(resolve, reject) {
            directionsService.route({
                origin: {'placeId': me.originId},
                destination: {'placeId': me.destinationId},
                travelMode: me.travelMode
            }, function(response, status){
                if (status === google.maps.DirectionsStatus.OK) {
                    // me.response = response;
                    directionsDisplay.setDirections(response);
                    resolve(response);
                } else {
                    window.alert('Directions config failed due to ' + status);
                }
            });
        });
        return p1
    }
    
    0 讨论(0)
  • 2020-12-23 09:26
           this.setState(
            {
                originId: input.originId,
                destinationId: input.destinationId,
                radius: input.radius,
                search: input.search
            },
            function() { console.log("setState completed", this.state) }
           )
    

    this might be helpful

    0 讨论(0)
  • 2020-12-23 09:29

    setState takes new state and optional callback function which is called after the state has been updated.

    this.setState(
      {newState: 'whatever'},
      () => {/*do something after the state has been updated*/}
    )
    
    0 讨论(0)
提交回复
热议问题