【问题标题】:Normalize API data for use in Redux规范化 API 数据以在 Redux 中使用
【发布时间】:2018-12-06 19:08:51
【问题描述】:

我有以下来自 API 的数据:

const data = {
  id: 1,
  name: 'myboard',
  columns: [
    {
      id: 1,
      name: 'col1',
      cards: [
        { id: 1, name: 'card1' },
        { id: 2, name: 'card2' }
      ]
    },
    {
      id: 2,
      name: 'col2',
      cards: [
        { id: 3, name: 'card3' },
        { id: 4, name: 'card4' }
      ]
    },
  ]
}

如您所见,基本上有 3 个嵌套级别。顶层包含idnamecolumns 列表。每个column 包含一个idname 和一个cards 列表。每个card 都有一个idname

我希望标准化数据以供在 Redux 中使用,如 here 所示。我正在使用normalizr 执行此操作,如下所示:

const card = new schema.Entity('cards');
const column = new schema.Entity('columns', {
  cards: [card]
});
const board = new schema.Entity('boards', {
  columns: [column]
});

normalize(data, board)

这会导致以下结果:

{
  "entities": {
    "cards": {
      "1": {
        "id": 1,
        "name": "card1"
      },
      "2": {
        "id": 2,
        "name": "card2"
      },
      "3": {
        "id": 3,
        "name": "card3"
      },
      "4": {
        "id": 4,
        "name": "card4"
      }
    },
    "columns": {
      "1": {
        "id": 1,
        "name": "col1",
        "cards": [1, 2]
      },
      "2": {
        "id": 2,
        "name": "col2",
        "cards": [3, 4]
      }
    },
    "boards": {
      "1": {
        "id": 1,
        "name": "myboard",
        "columns": [1, 2]
      }
    }
  },
  "result": 1
}

我似乎无法弄清楚的是如何根据 Redux 将每个部分(即:cardscolumnsboards)分成两个部分,即 byIdallIds上面引用的文章。

本质上,这是为了让 React 应用程序中的排序、排序等变得更容易。我使用的是最新版本的 normalizr (3.2.4)。

【问题讨论】:

  • 文档中的next page 对此进行了说明。本质上,您需要自己管理它们。
  • 下一页详细介绍了如何更新已采用正确格式的商店。这一切都说得通。但是,我仍然不确定如何首先创建初始规范化结构。根据我帖子中的示例,初始数据来自 API,然后我需要对其进行规范化并在每个部分中包含 byIdallIds。那是我不确定的部分。
  • 如果明天有时间,我会做一个例子来回答你。

标签: javascript reactjs redux normalizr


【解决方案1】:

Here is a CodeSandbox with an example 了解如何设置减速器来处理标准化状态。

基本上,您的每个实体都会得到类似的结果:

// lambda or function - whatever your preference is
const cardsById = (state = {}, action) => {
  // if, case, handler function - whatever your preference is
  if (action.type === 'ADD_DATA') { // or whatever your initial data load type is
    return { ...state, ...action.payload.cards }
  }
  return state
}

const allCards = (state = [], action) => {
  if (action.type === 'ADD_DATA') { // or whatever your initial data load type is
    return [...state, ...Object.keys(action.payload.cards)]
  }
  return state
}

const cards = combineReducers({
  byId: cardsById,
  allIds: allCards
})

然后将所有这些组合在一起:

export default combineReducers({
  cards,
  columns,
  boards
})

为此的动作创建者如下:

const addData = ({ entities }) => ({
  type: 'ADD_DATA',
  payload: entities // note the rename - this is not required, just my preference
})

// I used a thunk, but theory is the the same for your async middleware of choice
export const getData = () => dispatch => dispatch(addData(normalize(data, board)))

希望这会有所帮助。请记住,在添加或删除实体时,您需要同时维护每个实体的 byIdallIds

【讨论】:

  • 现在一切都说得通了。谢谢。
  • 也谢谢。但是如何在 redux store 中实现 crosstabless?说,如果我有卡片和 card_members 表,如何实现它们之间的关系?因为 Normalizing State Shape redux 文档说每种类型的数据在状态中都有自己的“表”。
猜你喜欢
  • 2019-05-14
  • 2019-06-02
  • 1970-01-01
  • 2016-02-11
  • 2017-08-16
  • 1970-01-01
  • 2017-04-25
  • 1970-01-01
  • 2018-01-27
相关资源
最近更新 更多