Redux Store-标准化

构建有效的 Redux Store

在构建 Redux store 时,需要记住以下两个事项:

  1. 数据不要重复。如果数据存储在多个位置,就没有单一数据源,就会浪费资源来使数据相互同步。

  2. store 尽量很浅。嵌套数据使 reducer 逻辑更复杂(尝试更新深度嵌套的数据会变得很复杂,并且很慢)

我们来看一个简单的示例。下面是一个 people 对象和一个 friends 数组。

const people = {
  kassidi: {
    name: 'Kassidi Henry',
    age: 24,
    favoriteMovie: 'Remember the Titans'
  },
  tyler: {
    name: 'Tyler McGinnis',
    age: 25,
    favoriteMovie: 'Fatigue: A JavaScript Story'
  },
  jake: {
    name: 'Jake Lingwall',
    age: 26,
    favoriteMovie: 'Casablanca'
  },
}

const friends = ['kassidi', 'jake']

现在,如果我想创建引用所有好友的新数组,代码很简单:

friends.map((friend) => people[friend])

我再也不会遇到数据一致性错误,因为我的所有数据只是引用其他数据。Redux 中的数据就应该这样。应该尽量避免数据重复并创建引用。

Redux 文档对这一模式进行了完美的总结:

“在更加复杂的应用中,需要让不同的实体相互引用。建议使状态尽可能标准化,没有任何嵌套。使对象中的每个实体存储时都具有 ID(作为键),并在其他实体或列表中使用 ID 引用它们。”

下一个提示是让 store 中的状态尽可能的浅,这样可以提高性能并降低复杂性。

假设有个如下所示的对象:

const books = {
  fiction: {
    fantasy: {
      teens: {
        0: {
          title: 'Harry Potter and the Nested Data',
          author: 'JK Rowling',
        }
      },
      adults: {}
    },
    romance: {},
    scifi: {},
  }, 
  nonFiction: {}
}

如果我们想要创建新的对象(因为我们从未希望修改原始状态),但是修改 Harry Potter 的标题,reducer 函数就会如下所示:

function books (state, action) {
  const { bookType, genre, category, id, title } = action
  if (action.type = CHANGE_TITLE) {
    return {
      ...state,
      [bookType]: {
        ...state[bookType],
        [genre]: {
          ...state[bookType][genre]: {
            [id]: {
              ...state[bookType][genre][id],
              title,
            }
          }
        }
      }
    }
  }

  return state
}

看看这个嵌套结构,呃!你懂得。不仅非常不高效,因为我们每次克隆状态时,都要使用操作符 (...) ,而且无论对于代码编写者还是阅读者来说,都十分难以阅读。

通过引用状态中的不同实体,并尽量减少状态的嵌套,可以提高应用性能,也能使你的代码更易于阅读。

标准化总结

标准化 是指删除重复数据并尽量减少代码嵌套。这样不仅使应用在 store 的状态中保持“单一数据源”——更新状态的 reducer 逻辑也能保持整洁、合理。最终,标准化 Redux store 将使查询更高效和一致。

更多资料

  • Normalizr
  • Redux 文档中的 State 范式化 / 英 部分

你可能感兴趣的:(Redux Store-标准化)