最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Reducing redux-thunk boilerplate - Stack Overflow

programmeradmin2浏览0评论

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?

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?

Share Improve this question edited May 26, 2016 at 3:40 AndrewMcLagan asked May 25, 2016 at 8:16 AndrewMcLaganAndrewMcLagan 14k25 gold badges96 silver badges166 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 9

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 plicated, you might want to consider redux-saga or redux-observable.

Unfortunately, there is no mon way in redux munity to approach this exact problem. I personally feel that people should not be afraid to write their own custom wrappers around redux to deal with exactly such situations.

I created a library called redux-tiles, which actually has almost exact API as you want :) For instance, you code will look like the following:

import { createTile } from 'redux-tiles';
const login = createTile({
  type: ['user', 'login'],
  // params is an argument with which you call an action
  fn: ({ api, params }) => api('POST', '/auth/login', params),
});

As you can see, there are no constants here, as well as a reducer. These things are created automatically, so you don't have to do it, as well as testing it. There are other features, like nesting (so same function will be applied for fetching items by id, for instance, but they will be correctly updated inside reducer) and caching. You can checkout examples here.

Redux-saga is a good thing too, but it is more if you need some sort of reactivity, if you need more traditional approach, just a little bit more convenient way to describe your actions and bine them, without repeating yourself, then I find my library to be a perfect match.

发布评论

评论列表(0)

  1. 暂无评论