Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reducing redux-thunk boilerplate

When writing redux-thunk functions, known as thunks there is allot of boilerplate that could be easily abstracted away. For example in most of our async API calls we are doing the following, without any side-effects:

export const LOGIN_REQUEST = 'my-app/auth/LOGIN_REQUEST';
export const LOGIN_RECIEVE = 'my-app/auth/LOGIN_RECIEVE';
export const LOGIN_FAILURE = 'my-app/auth/LOGIN_FAILURE';

// ... reducer code here

export function login(loginHandle, password) {
  return (dispatch, getState, api) => {
    dispatch({ type: LOGIN_REQUEST });

    api.post('/auth/login', { loginHandle, password }).then(
      response => dispatch({ type: LOGIN_RECIEVE, response }),
      error => dispatch({ type: LOGIN_FAILURE, error })
    );
  };
}

Easy! Although as this covers at least 70% of our requests I'm sure there is an elegant way to abstract away allot of the above code to something like this (pseudo code):

export function login(loginHandle, password) {
  return (dispatch, getState, api) => api('POST', LOGIN_REQUEST, '/auth/login', { loginHandle, password });
}

When we need to check the state and other side effects we can go back to a proper thunk. Although for most cases... we could cut this down?

Any elegant ideas?

like image 229
AndrewMcLagan Avatar asked May 25 '16 08:05

AndrewMcLagan


1 Answers

Redux Thunk lets you inject a custom argument since 2.1.0.

const api = createApi() // you would write this function
const store = createStore(
  reducer,
  applyMiddleware(thunk.withExtraArgument(api))
)

// your action creator:
function fetchUser(id) {
  return (dispatch, getState, api) => {
    // you can use api here
  }
}

In the future, if your thunks get too complicated, you might want to consider redux-saga or redux-observable.

like image 124
Dan Abramov Avatar answered Sep 27 '22 19:09

Dan Abramov