Skip to content

Instantly share code, notes, and snippets.

@rickharrison
Last active October 2, 2015 18:07
Show Gist options
  • Save rickharrison/39e9e0ad15f7eafdde1b to your computer and use it in GitHub Desktop.
Save rickharrison/39e9e0ad15f7eafdde1b to your computer and use it in GitHub Desktop.

I have a question around handling actions for asynchronous requests to an API. Imagine that you have a middleware, which will hit an API and fire off 3 actions as is common in best practice redux/flux. One for the initial request, one for success, and one for failure. Typically you can set a fetching flag and store an error if there is one.

Here is some basic example pseudo-ish code demonstrating this:

import {
  CREATE_FOO_REQUEST,
  CREATE_FOO_SUCCESS,
  CREATE_FOO_FAILURE
} from './actions';

const initialState = {
  entity: null,
  isFetching: false,
  error: null
}

export default function foo (state = initialState, action) {
  switch (action.type) {
    case CREATE_FOO_REQUEST:
      return {
        ...state,
        isFetching: true,
        error: null
      };

    case CREATE_FOO_SUCCESS:
      return {
        ...state,
        entity: action.payload,
        isFetching: false,
        error: null
      };

    case CREATE_FOO_FAILURE:
      return {
        ...state,
        isFetching: false,
        error: action.payload
      };
  }
}
const FooList = React.createClass({
  handleSubmit: function (event) {
    event.preventDefault();
    
    // validate data
    
    this.props.createFooResource({ field1, field2 });
  }

  render: function () {
    if (this.props.isFetching) {
      return <p>Loading...</p>;
    }
    
    if (this.props.error) {
      return <p>Error: {this.props.error}</p>
    }
    
    return <form>...</form>;
  }
});

function mapStateToProps (state) {
  return {
    isFetching: state.foo.isFetching,
    error: state.foo.error
  };
}

const mapDispatchToProps = {
  createFooResource
};

export default connect(mapStateToProps, mapDispatchToProps)(FooComponent);

My question is how do you know in the component that the action is completed and you can now either display a success message or transition to another page using react-router. It is extremely easy to listen for the loading and error flags, but how do you know when a request has gone through successfully and to do something. A naive approach when not using redux/flux would look like this:

handleSubmit: function () {
  createFooResource().then(function () {
    this.history.replaceState(...);
  }).catch((err) => {
    this.setState({ error: err });
  })
}

What is the best practice to know when something is completed in redux with the typical 3 actions for asynchronous behavior?

@Fauntleroy
Copy link

You could also have an action that fires when the form initializes and resets any old state.

@Fauntleroy
Copy link

In our current setup...

  getStateFromStores: function () {
    var state = {
      user: UserStore.getUser(),
      loading: UserStore.isUpdatingProfile(),
      error: this.initialized ? UserStore.getUpdatingProfileError() : null
    };
    this.initialized = true;
    return state;
  },

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment