在redux中扩展本质

问题描述 投票:2回答:2

我的州看起来像这样:

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减速器用于一个和多个物品的手柄加载状态(isFetching = true)?

javascript redux
2个回答
4
投票

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

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

让我们从这个声明开始:

它适用于带有列表的页面,但文章模型因索引路径而异,并获得路径

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

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

在这种情况下,我将有三个动作:

getAllArticles()

getArticlesById(id)

putArticles(articles)

两个获取文章操作将负责发出请求,格式化数据。然后他们获取这些数据并将其传递给putArticlesconst 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} } } 实际上会调度reducer正在侦听的操作。

你的方法看起来像这样:

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

规范化数据

我要看的下一步是规范化您的数据。实际上,您已经完成了将实体拆分并将分页信息与实际实体列表分开的相当好的工作。

我会按实体类型打破你的商店。

Normalizr

规范化数据可防止您使用嵌套资源列表(文章>用户>注释,作为示例)。你已经完成了这项工作,使用像Normalizing Redux State Shape这样的库来形式化它将允许你标准化处理数据的方式。

我会将分页移动到单个实体(用户,文章)。这样就可以根据类型将事物整齐地分开,并防止出现大量不相关的数据。

深入整体规范化超出了SO问题的范围,但请看看这两个链接:

Updating Normalized Data

users


2
投票

我认为我的结构是多余的,因为创建了两个简化器来描述一个实体。

你可以使用2个实体:articlesisFetching来存储所有用户和文章数据,包括来自api/articlesstate = { users: { 1: { // userId === 1 name: 'John', // user properties articles: [1, 2, 5], // article ids associated with user } }, articles: { 1: { // articleId === 1 title: '...', isFetching: true, } } } 状态和部分数据:

api/articles/:id

然后,当您成功从SET_ARTICLE_DATA检索文章时,您可以使用文章iddata发送case SET_ARTICLE_DATA: return { ...state, // clone existing articles [action.id]: { // replace article with id === `action.id` with received data ...state[action.id], // not needed if `action.data` has everything u need ...action.data, isFetching: false, // can use object destructuring on `state[action.id]` to remove this key too } } 操作,并替换文章reducer中的部分文章数据(假设您将文章状态保存在单独的reducer中):

qazxswpoi
© www.soinside.com 2019 - 2024. All rights reserved.