Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error at the Action? #21

Open
GantMan opened this issue Oct 28, 2015 · 14 comments
Open

Error at the Action? #21

GantMan opened this issue Oct 28, 2015 · 14 comments

Comments

@GantMan
Copy link

GantMan commented Oct 28, 2015

I'm coming to flux from a Rails/Ruby world (gasp!)

As I'm wrapping my head around Flux and standards (like FSA) I'm finding some questions pop up in my head, and whom better to answer than the FSA community/creator.

In FSA why is error state the job of the Action? That seems like we've overstepped, and for the wrong reasons. I don't think it's the action's job to choose something like validity (validity is a state).

An action is an abstract description of an operation to be performed. In databases you have transactions, in Android you have Intents, and in Rails you can attempt to modify a Model, but there's no guarantee that it will succeed, or yield a change. Should that be an error state? I think the reducer knows best.

Think of this:
I can't buy -1 of something, but who's job should it be to tell me that? When I press the minus button on a cart, should my action check state to see if I'm at zero, and violate separation of concerns? Or should it just fire the action and my reducers take care of state (one managing my cart number at zero and another showing a red exclamation mark animation). Ok, not a great example, but I think it expresses the point. I feel errors shouldn't be part of actions, and I'm interested in hearing why otherwise.

EDIT

TL:DR; The error flag in FSA is bad

@tomatau
Copy link

tomatau commented Nov 2, 2015

I prefer to see actions more closely represent business logic, and so often have some definition of how to handle errors. Logic around errors, validity and defensive defaults etc, can be different on a use-case by use-case basis even within the same app -- so I prefer to have this described at the action level.

Also, when handling any side effects, such as transactions, these definitely do not belong in a reducer and so the error handling must happen in the action layer for these situations.

@GantMan
Copy link
Author

GantMan commented Nov 2, 2015

Checking for errors at actions + async can allow for race conditions if you have sophisticated application. Business logic belongs in a controller-like component, and reducers are model-like.

I'll just have to disagree. Actions seem like a bad place to enforce protection of state in my opinion.

@tomatau
Copy link

tomatau commented Nov 2, 2015

How could actions introduce race conditions unless you fire off multiple actionCreators at the same time? Which is a pattern that is discouraged.

@GantMan
Copy link
Author

GantMan commented Nov 2, 2015

I'm using redux-thunk to handle async actions inside my actionCreators. I could then attemptLogin which will have the actions REQUEST_LOGIN and RECEIVE_LOGIN respectively. Between the two, you could have the user press CANCEL_LOGIN.

Don't focus on the example, but async introduces variance of order, simply by definition.

@tomatau
Copy link

tomatau commented Nov 2, 2015

I'm in the habit of using flags in my reducers such as isPending so that the sequence of dispatched actions can be handled appropriately by the components responding to the said state changes. Action creators dispatching error actions can facilitate this process in sophisticated applications.

You're suggesting that components should initiate transactions, pass these results to the dispatch through an action creator and then the reducers all individually handle the response/error?

@GantMan
Copy link
Author

GantMan commented Nov 2, 2015

close. The reducers set the state to error. They don't handle them. Basically, reducers are in charge of transforming state (as they should). Ultimately, I guess that's where we differ. We both agree that the problem needs to be handled (via flags/error or whichever we choose). The crux is where and when. And that depends on definition.

For me actions are signals that should not be stopped or stunted. If a button is pressed, let the associated action happen, because perhaps later or in some other aspect of your application you'll want to do something, like log user behavior or show a friendly message.

Reducers can receive error messages from actions, but ultimately they transform data. They should hold the rules of what error state should be. I hate to use the hackneyed DRY concept, but actions can possibly come from a multitude of places, and what qualifies state changes really only matters in one spot, the reducer.

@tomatau
Copy link

tomatau commented Nov 2, 2015

If the reducers are not handling the transaction fail event, what is?

@GantMan
Copy link
Author

GantMan commented Nov 3, 2015

The "Dumb" components respond to the state change. Error state can cause some components to become non-editable, while others turn red, and even others display messages. When the props are mapped to state with connect, the components can then react accordingly to their own properties, powered by redux state.

@tomatau
Copy link

tomatau commented Nov 3, 2015

That didn't answer my question.

For example.. when you make an AJAX request... where do you put your onError or try/catch for this transaction?

@GantMan
Copy link
Author

GantMan commented Nov 3, 2015

Sorry I missed what you meant and thank you for having this philosophical conversation with me :)

A response that is an error (not a 200) is passed on through the action as to a reducer. The action only cares a result has been returned (usually aptly named something like RECEIVED_X).

The reducer can then set state based on the payload. Now the reducer translates error state, like 401 can set state to "unauthorized". Which then prompts the correct behavior to deal with that state.

@tomatau
Copy link

tomatau commented Nov 3, 2015

OK so you still put the transaction in your actionCreator.

So when setting error messages based on say a connection error or invalid response from the server, you would still send an action that resembles a successful transaction -- The error information would still need to be dispatched in an action.

@GantMan
Copy link
Author

GantMan commented Nov 3, 2015

Yes. I apologize for the confusion. My gripe is the error flag in FSA.

@tomatau
Copy link

tomatau commented Nov 3, 2015

Ahh! Yes you're not the only one! I'm not happy with that either and have been protesting for an API change around the error flag too :)

I think you should check existing issues before opening a new one #17

@GantMan
Copy link
Author

GantMan commented Nov 3, 2015

O good! I'm glad 👍

and thank you again for your time in discussing redux with me :) It really helps me grok the concepts more deeply. I hope this thread helps others!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants