11

在编写redux-thunk函数时,称为thunk,有很多样板文件可以很容易地抽象掉。例如,在我们的大多数异步 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。虽然在大多数情况下......我们可以减少这个?

有什么优雅的想法吗?

4

2 回答 2

9

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

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

于 2016-05-25T12:05:21.283 回答
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 中正确更新)和缓存。您可以在此处查看示例。

Redux-saga 也是一个好东西,但是如果你需要某种反应性,它会更多,如果你需要更传统的方法,只是更方便的方式来描述你的动作并将它们组合起来,而不是重复自己,那么我发现我的图书馆是一个完美的匹配。

于 2017-09-04T00:03:47.790 回答