javascript - redux 中本质的扩展

标签 javascript redux

我的状态是这样的:

state = {
  entities: {
    users: {},
    articles: {},
  },
  pagination: {
    articlesByUser: {
      1: { // userId = 1
        isFetching: true,
        ids: [],
      },
      2: { // userId = 2
        isFetching: true,
        ids: [],
      },
    },
  },
}

对于带有列表的页面,它工作正常,但是 index 路由和 get 路由的文章模型不同。

响应 index 路由:

$ curl http://api//articles
[{
  "id": 0,
  "user_id": 0,
  "title": "...",
  "short_description": "...",
  ...
}
...
]

响应 get 路由:

$ curl http://api//articles/0
{
  "id": 0,
  "user_id": 0,
  "title": "...",
  "body": "...",
  "meta": {...},
  "view_count": 100,
  ...
}

实体不同。 GetModel 请求扩展 IndexModel。因此 pagination reducer 的状态应该是这样的:

pagination: {
  articlesByUser: {
    1: { // userId = 1
      isFetching: true,
      ids: [],
    },
    2: { // userId = 2
      isFetching: true,
      ids: [],
    },
    ...
  },
  articleByArticleId: {
    1: { // articleId = 1
      isFetching: true,
    },
    ...
  }
},

如何在这种情况下更好地构建 pagination reducer 以处理一篇和多篇文章的加载状态 (isFetching = true)?

最佳答案

我不知道您提到的模型是什么意思;我的假设是你在谈论后端的模型,但这并没有真正影响我们,所以我将忽略它们。

在 Redux 中使用操作来获取和格式化数据

让我们从这个声明开始:

It works fine for pages with lists, but the article models differ for the index route and get the route

这实际上并不重要!路线之间的数据不同是可以的(即使它并不理想)。

我不知道您目前在哪里处理您的 API 请求,但我建议将它们放入 Redux Actions。使用中间件 Redux Thunk我们可以在我们的 Action 创造者中拥有功能。 Action 的一部分工作是为 reducer 准备数据。这意味着我们可以在操作中使用函数来格式化数据,这样当它到达 reducer 时它总是相同的。这意味着我们不需要编写许多类似的 reducer 来处理相同的实体类型,保持事物干燥并使其更易于维护。

在这种情况下,我将执行三个操作:

getAllArticles()

getArticlesById(id)

putArticles(文章)

两个 get article 操作将负责发出请求、格式化数据。然后,他们获取这些数据并将其传递给 putArticles,后者实际调度 reducer 正在监听的操作。

你的方法看起来像这样:

const getAllArticles = () => {
   return (dispatch, getState) => {
      fetch(yourRoute).then((json) => {
        const formattedData = json // format/normalize your data here
        dispatch(putArticles(formattedData))
      }
   }
}

const getArticleById = (id) => {
   return (dispatch, getState) => {
      fetch(yourRoute + id).then((json) => {
        const formattedData = json // format/normalize your data here
        dispatch(putArticles(formattedData))
      }
   }
}

const putArticles = (articles) => {
   return {
      type: 'PUT_ARTICLES',
      payload: {articles}
   }
}

规范化数据

我要考虑的下一步是规范化您的数据。实际上,您在拆分实体并将分页信息与实际实体列表分开方面做得非常好。

我会按实体类型分割您的商店。

state = {
   articles: {
      entities: { /* each article by ID */},
      result: [/* array of ID, primary used for looping */],
      pagination: { /* various pagination methods */ }
   },
  ...
}

规范化数据可以防止您形成嵌套的资源列表(例如,文章 > 用户 > 评论)。您几乎已经完成了这项工作,使用类似 Normalizr 的库将其形式化将使您能够标准化处理数据的方式。

我会将分页移动到单个实体(用户、文章)中。这使事物按类型整齐地分开,并防止拥有大量不相关数据的列表。

作为一个整体深入规范化超出了 SO 问题的范围,但请查看以下两个链接:

Normalizing Redux State Shape

Updating Normalized Data

关于javascript - redux 中本质的扩展,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50062507/

相关文章:

javascript - 基于参数的单例模式在 JavaScript 中创建 Promise

javascript - 应用 API 响应转换的最佳位置

javascript - 如何从 npm install 中包含样式表和 javascript

javascript - 如何通过客户端javascript函数触发服务器端程序(shell脚本)的执行?

JavaScript、React - 发送多个同时的 ajax 调用

javascript - 如何使用功能组件从 Redux 存储中检索数据并避免 useSelector 和 useDispatch

angular - 我应该在每个路由器导航上重置我的 redux 存储吗?

javascript - 我可以在第二次触发事件时执行一组不同的代码吗?

javascript - 使用 jQuery 监听浏览器宽度/高度变化

javascript - javascript 中的变量行为,使用 += 运算符时旧值不会被覆盖