flux-standard-action: What is the reason error property is boolean?

as opposed to an instance of Error object. Boolean flag is vague. It just says what the error is and does not standardise the method of getting error description. Docs say that payload by convention should be an Error object.

About this issue

Most upvoted comments

The error design of Flux Standard Actions is completely unworkable for us; we’ve decided to not use Flux Standard Actions for that reason.

  1. As mentioned, the ‘error’ boolean is redundant. For us, an error is any action that has a type that ends with ‘ERROR’.
  2. We almost always require the original payload when handling error actions. For example, when we have an error updating a model, we update our state to contain the list of field that have not been successfully updated. It’s certainly possible to put the original payload into meta.payload or payload.payload or something like that, but that’s just silly. In our “FSA”, the payload property of an error action is always the original payload.
  3. Given that most error objects are the result of HTTP actions, we have a standard field that contains the HTTP status code. Not all errors have to have this field, but when they do, it’s in a standard place.
  4. We make the Error object required rather than optional, and put it in the error property of the action.

I think the original intent of adding error as a boolean property can be deduced from the example in the readme.

{
  type: 'ADD_TODO',
  payload: {
    text: 'Do something.'  
  }
}

{
  type: 'ADD_TODO',
  payload: new Error(),
  error: true
}

There are no redundancies in this example.

Due to the way people use Redux, though, it starts to get redundant.

{
  type: 'ADD_TODO_REQUEST',
  payload: {
    text: 'Do something.'  
  }
}

{
  type: 'ADD_TODO_SUCCESS',
  payload: {
    text: 'Do something.'
  }
}

{
  type: 'ADD_TODO_FAILURE',
  payload: new Error(),
  error: true
}

Perhaps the correct approach would be to separate app concerns from asynchronous concerns and instead of doing request -> success | failure, it’s better to do request -> success (triggers action<foo>) | failure (triggers error<foo>), where action<foo> is equivalent to { type: 'foo' } and error<foo> is equivalent to { type: 'foo', error: true } with their respective payloads.

The only issue this brings are optimistic updates. This could be solved, though, by triggering actions that queue the change when the request is made and then committing when it succeeds or reverting if it fails.

I came from SO for this same issue.

When an error occurs, it IS an action. It is not an action with an error.

I forsee conditional logic sprinkled all over your action handling code checking for an error property when you could simply be handling an error action.

If you are using something like redux, you can have a dedicated reducer handling errors.

A better design would have been to standardize the error payload so handling is streamlined.

Another thing is properties that ‘MAY’ exist. How is that even standard then? More conditional logic for me.

An action should have ONLY two properties. A TYPE and a PAYLOAD. Everything else, error messages, meta data etc should be in the PAYLOAD. That is a standard.

+1 for error property being any object with a message property.

You can serialise an Error object:

JSON.stringify(new Error("my message"), ['message'])
// "{"message":"my message"}"

You can even serialise the stack if you so wish…

Having an error boolean flag to me seems like a duplication of action information. It’s good to have a place for a standardised error format that can hold general information. Storing state specific IDs for failure in the meta data also seems like the wrong place.

For example, an action sequence that performs a batch update with optimism.

{ type: BATCH_ITEM_UPDATE_PENDING, payload: {items[]}, meta: {actionId} }
{ type: BATCH_ITEM_UPDATE_SUCCESS, payload: {successful_item_ids[]}, meta: {actionId} }
{ type: BATCH_ITEM_UPDATE_FAIL, payload: {failed_items[]}, meta: {actionId} }

The meta property contains an id specific to the action sequence – not the state changes. The payload contains multiple ids (and more), for any items that failed and needs reverting from the optimistic update (or whatever else – maybe error messages in the app?).