首页 > 解决方案 > 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。因此paginationreducer 的状态应该是这样的:

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

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

标签: javascriptredux

解决方案


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

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

让我们从这个声明开始:

它适用于带有列表的页面,但文章模型对于索引路由和获取路由不同

这其实无所谓!路线之间的数据不同是可以的(即使它不理想)。

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

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

getAllArticles()

getArticlesById(id)

putArticles(articles)

两个获取文章操作将负责发出请求、格式化数据。然后他们获取这些数据并将其传递给putArticles实际调度减速器正在侦听的操作。

你的方法看起来像这样:

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 问题的范围,但请查看以下两个链接:

规范化 Redux 状态形状

更新规范化数据


推荐阅读