javascript - 像 api 工厂一样对多个 Ajax 调用重用相同的 reducer 和史诗?

标签 javascript reactjs redux rxjs redux-observable

使用相同的 reducer 来更新状态的不同部分是反模式吗?

就像我的数据缩减器有一个 GET_DATA_DONE 操作,更新 state.data,然后在另一个实例中,您使用获取其他内容并调用 GET_DATA_DONE 来更新 state。其他东西

或者你会做类似GET_SOMETHING_DATA_DONE之类的事情......多个差异操作做同样的事情吗? (几乎)

reducer .js

export const reducer = (state, action) => {
  switch (action.type) {
    case actions.GET_DATA_REQUESTED:
      return { ...state, isLoading: true };
    case actions.GET_DATA_DONE:
      return { ...state, isLoading: false, data: action.payload };
    case actions.GET_DATA_FAILED:
      return { ...state, isLoading: false, isError: true }
    default:
      return state;
  }
};

actions.js

export function getDataRequested() {
  return {
    type: 'GET_DATA_REQUESTED'
  };
}

export function getDataDone(data) {
  return {
    type: 'GET_DATA_DONE',
    payload: data
  };
}

export function getDataFailed(error) {
  return {
    type: 'GET_DATA_FAILED',
    payload: error
  };
};

export function getDataEpic(action$) {
  return action$.ofType(GET_DATA_REQUESTED)
    .mergeMap(action =>
      ajax.getJSON(action.url)
        .map(response => getDataDone(response))
        .catch(error => getDataFailed(error))
    );
}

构建应用程序的最佳方式是什么,让 getDataEpic 充当 API 工厂,并且从 getDataDone(response) 返回的数据可以传递给另一个应用程序 reducer 根据操作更新状态的一部分,例如使用 getDataDone 的城市操作 reducer 调度另一个使用响应更新 state.cities 的操作?

编辑:我已经制作了一个带有 rx-observable 和 redux 的应用程序,调用 3 个不同的 api,但我最终得到了很多重复的代码,并且对解决方案不满意,所以我想构建一个正确架构的应用程序

希望我说得足够清楚。

非常感谢!

最佳答案

如果处理它自己的 child 的状态,我不认为这是一种反模式,但如果使用太多,它肯定会给你带来麻烦。让它修改完全不相关的状态是一种明确的反模式。 According to the docs第一行就一语中的。

For any meaningful application, putting all your update logic into a single reducer function is quickly going to become unmaintainable.

我们不是在谈论“所有数据”,而是在谈论来自单个 API 调用的所有数据。

设置加载标志并不太复杂,但在现实世界的应用程序中,对于同时设置加载标志、错误标志和“数据”的 reducer 来说,会变得更加复杂。这是假设我们甚至知道所请求的数据是什么。

在您的示例中,如果目的是通过化简器创建 API 工厂,我们必须假设 API 可以返回任意数量的不同数据结构,现在它可以是 stringint 但如果它是一个深层嵌套的 Object 呢?您将如何访问此数据并将其与另一条数据区分开来?

<小时/>

假设我们有一个应用程序,其数据结构仅用于处理错误:

{
  "errors": {
    "byId": {
      "1": {
        "code": 500,
        "message": "There was an internal server error"
      },
      "2": {
        "code": 400,
        "message": "There was another error."
      },
      "3": {
        "code": 999,
        "message": "Wow! weird error."
      },
    },
    "all": ["1", "2", "3"]
  }
}

我可能有一个 byId reducer ,它返回一个计算出的键,并使用另一个 reducer 作为值。

byId = (state={}, action) => {
  if (action.type === 'ADD_ERROR') {
    ...state,
    [action.id]:error_reducer(state[action.id], action)
  } else {
    return state
  }
}

error_reducer 可能看起来像

errorReducer = (state={}, action) => {
  if (action.type === 'ADD_ERROR') {
    code: action.code,
    message: action.message
  } else {
    return state
  }
}

我认为让 errorReducer 处理代码和消息更有意义,因为我们知道它们都是相互包含的数据片段,其中每个错误都是互斥的(不同的 id),因此需要它们自己的 reducer 。

在处理实际应用程序时,这样做的另一个主要优点是,当数据分离时,一个操作可以更新应用程序的许多不同区域的状态。当 reducer 处理多个状态时,这些绑定(bind)状态会变得更难更新。

<小时/>

您可以在 reducer 中使用许多不同的模式,它们都没有错,但是我发现这种模式非常适合我,并且我已经在一个相当复杂的生产应用程序中成功地使用了它。

话虽如此,AJAX 函数的一种可能方法是编写一个通用操作来接受包含您的调度的对象。

通过使用像 redux-thunk 这样的库您可以执行多个调度,以使用不同的数据更新状态的不同部分。我不会在这里解释 redux-thunk 因为我认为它超出了问题的范围。

示例对象可能如下所示:

{
  getDataRequested: function () {
    return {
      type: 'GET_DATA_REQUESTED'
    };
  },
  getDataFailed: function (error) {
    return {
      type: 'GET_DATA_FAILED',
      payload: error
    };
  },
  getDataDone: function (data) {
    return {
      type: 'GET_DATA_DONE',
      payload: data
    };
  }
}

然后您可以将此回调对象以及 API 端点、REST 请求类型等传递给您的主 AJAX 函数。

我希望这会有所帮助。

关于javascript - 像 api 工厂一样对多个 Ajax 调用重用相同的 reducer 和史诗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47250757/

相关文章:

javascript - NodeJS - 使用 mongoose 解析大型集合

reactjs - react Js : export problems '(possible exports: default)'

reactjs - Redux 存储在第一次单击按钮时不会更新

javascript - React Material UI 1.0 在更改时选择多个参数

javascript - 当单击另一个数组中的另一个单独项目同时从第一个数组中删除该项目时,从一个数组中随机显示项目?

javascript - 数据表过滤器不起作用

javascript - 突出显示菜单项及其子菜单项

javascript - 基于 Redux 状态返回值的货币实用函数?

reactjs - React 高阶组件与父组件

javascript - 不熟悉我遇到的这种 javascript 语法