Redux 中的 selectors 是用来从 Redux 的状态树(state tree)中抽取并派生数据的函数。在 Redux 应用中,全局状态是以一个单一的对象存储的,由于这个状态树可以非常庞大并包含许多不同的数据片段,直接从中获取数据可能会既复杂又繁琐。Selectors 就是为了简化访问状态树中的数据而存在的。
Selectors 的主要职责和作用有:
-
封装状态结构:Selectors 提供了一个抽象层,允许组件不必了解状态树的具体结构即可读取状态。这意味着如果状态树的结构发生了变化,只需更新相应的 selectors,而无需修改所有使用了这部分状态的组件。
-
计算派生数据:Selectors 可以用来计算派生数据,即根据状态树中的原始数据来计算新的数据表示。比如,从一个包含多个对象的数组中过滤出符合特定条件的对象,或者计算某些数据的总和。
-
性能优化:配合库如 Reselect,selectors 可以通过记忆(memoization)技术避免不必要的计算。这意味着只有当 selector 的输入(即状态树的相关部分)发生变化时,selector 才重新计算,否则它会返回上一次计算的结果,从而提高应用的性能。
-
重用和组合:Selectors 可以被重用于不同的组件中,也可以组合在一起构建更复杂的 selectors,这有助于减少代码冗余并保持逻辑的一致性。
例子
假设我们有一个 Redux 状态,其中包含一个商品列表,每个商品都有价格和类别。如果我们想要获取所有电子类别商品的总价格,我们可以写一个 selector 来实现这一点:
javascript// state结构示例 const state = { products: [ { id: 1, name: '手机', category: '电子', price: 599 }, { id: 2, name: '平板电脑', category: '电子', price: 799 }, { id: 3, name: '手表', category: '配饰', price: 199 } // 更多商品... ] }; // Selector const selectElectronicProductsTotalPrice = (state) => { return state.products .filter(product => product.category === '电子') .reduce((total, product) => total + product.price, 0); }; // 使用Selector const totalPrice = selectElectronicProductsTotalPrice(state); console.log(totalPrice); // 输出应为 1398
在这个例子中,selectElectronicProductsTotalPrice
是一个 selector,它首先过滤出所有电子类别的商品,然后计算并返回这些商品价格的总和。通过这种方式,我们不仅封装了对状态树的查询逻辑,还使得这段逻辑更易于测试和重用。