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

Dispatching an action on error (error handling) #78

Closed
wvengen opened this issue May 24, 2016 · 4 comments
Closed

Dispatching an action on error (error handling) #78

wvengen opened this issue May 24, 2016 · 4 comments

Comments

@wvengen
Copy link
Contributor

wvengen commented May 24, 2016

I'm trying to come up with a clean way to handle errors returned by the API. When a request fails, I'd like to show a notification that removes after a timeout. For my purpose, that means dispatching an action (which is thunk-based to be able to submit the hide-notification action after a timeout, e.g. re-notif).

My current solution is to modify all rest-api actions and add an error-handling callback, making sure to call the original callback if it was supplied. It's ugly (I guess it could be improved a bit, but main points are the need to change all existing actions, and the way in which the callback is hooked).

const rest = reduxApi({ /* ... */ });

function withErrorHandler(actionCreator) {
  return function() {
    const callback = typeof(arguments[arguments.length-1]) === 'function' ? arguments[arguments.length-1] : undefined;
    const creatorArgs = callback ? [...arguments].slice(0, -1) : arguments;
    return (dispatch) => {
      dispatch(actionCreator(...creatorArgs, (error, data) => {
        error && dispatch(notifs.notifSend({message: error.message, kind: 'danger', dismissAfter: 3000}));
        callback && callback(error, data);
      }));
    };
  };
}

export default {...rest, actions: Object.keys(rest.actions).reduce(
  (memo1, key1) => { return {...memo1, [key1]: Object.keys(rest.actions[key1]).reduce(
    (memo2, key2) => { return {...memo2, [key2]: withErrorHandler(rest.actions[key1][key2]) }; }, {}
  )}}, {}
)};

I've tried others things that didn't work out:

  • Wrapping my final reducer in a function, that whenever a redux-api failure action is dispatched, the state is modified directly to show the action. Doesn't work because I need thunk-based actions, which make the reducer impure.
  • Subscribing to the store, doesn't work because there are no actions to watch, just state changes (and not all actions may trigger the subscriber means possibly losing errors).

Any suggestions to improve this?

@lexich
Copy link
Owner

lexich commented May 25, 2016

You only need to write middleware and catch errors actions using RegExp

const restApiErrorCatcher = ()=> (next)=> (action)=> {
  if (/^@@redux-api@.*_error$/.test(action.type)) {
     const { error } = action;
     error && next(notifs.notifSend({message: error.message, kind: 'danger', dismissAfter: 3000}));
  }
  return next(action);
}

@wvengen
Copy link
Contributor Author

wvengen commented May 25, 2016

Wow, that's much much better indeed, thanks!!

@wvengen wvengen closed this as completed May 25, 2016
wvengen added a commit to foodcoops/foodsoft-shop that referenced this issue May 25, 2016
@wvengen
Copy link
Contributor Author

wvengen commented May 25, 2016

btw, its /^@@redux-api@.*_fail$/ but thanks a lot again

@lexich
Copy link
Owner

lexich commented May 25, 2016

Oh, its my fail :)

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