减少redux-thunk样板

时间:2016-05-25 08:16:51

标签: javascript reactjs redux redux-thunk redux-saga

当编写redux-thunk函数(称为 thunks )时,可以轻松地抽象掉一些样板文件。例如,在我们的大多数异步API调用中,我们正在执行以下操作,没有任何副作用:

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 })
    );
  };
}

轻松!虽然这至少覆盖了我们70%的请求,但我确信有一种优雅的方法可以将上述代码抽象为类似的内容(伪代码):

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

当我们需要检查状态和其他副作用时,我们可以回到适当的thunk。虽然在大多数情况下......我们可以减少它吗?

任何优雅的想法?

2 个答案:

答案 0 :(得分:8)

Redux Thunk允许您从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
  }
}

将来,如果您的游戏过于复杂,您可能需要考虑redux-sagaredux-observable

答案 1 :(得分:0)

不幸的是,在redux社区中没有通用的方法来解决这个问题。我个人认为人们不应该害怕在redux周围编写自己的自定义包装器来处理这种情况。

我创建了一个名为redux-tiles的库,它实际上具有您想要的几乎完全的API :)例如,您的代码将如下所示:

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),
});

如您所见,此处没有常量,还有减速器。这些东西是自动创建的,因此您不必执行此操作,也不必对其进行测试。还有其他功能,例如嵌套(因此,相同的功能将应用于通过id获取项目,但它们将在reducer内正确更新)和缓存。您可以查看示例here

Redux-saga也是一件好事,但是如果你需要某种反应,如果你需要更传统的方法,只需要一点点方便的方式来描述你的行为并将它们结合起来,而不重复自己,那就更好了。然后我发现我的图书馆是一个完美的匹配。