Redux 中使用 Selector 技巧
在 Redux 应用程序中使用 Selector 可以让代码更加高效、可读性更强。Selector 本质上是一个纯函数,负责将存储于 Redux store 中的 state 转换成渲染视图所需的数据结构。在使用 Selector 时,需要考虑一些技巧和最佳实践,本文将对这些问题进行详细讲解和指导。
一、避免对完整 state 树执行计算 在 Redux 中,selector 不应该对完整的 state 树执行计算,而应该只关注它所依赖的那一部分 state。这是因为 Redux Store 中包含的 state 树可能非常大,而且可能包含许多嵌套的子对象。如果每次调用 Selector 都执行完整的计算,会导致性能问题。 因此需要注意选择使用state的哪一部分进行计算。
二、使用 reselect 库增加性能 Reselect 是一个小型且高效的库,它最大化了 Selector 的性能,并允许我们避免不必要的计算。Reselect 库可以记忆 Selector 的结果,只在其依赖的 state 有变化时进行重新计算,以避免不必要的计算和大量的结果缓存。
三、Selector 返回值应该是纯的数据结构 Selector 函数的返回值应该是一个简单的、不可变的 JavaScript 数据结构,这样可以最大限度地提高性能和可读性。返回的对象应该尽可能少地依赖于 state 数据,已经通过前面的计算过程将 state 转换成 UI 组件所需要的数据结构。常见的返回数据可为普通的对象,数组等。
四、大维度的 Selector 可以通过组合实现 Selector 可以通过组合来实现大维度的 state tree 的数据获取。组合的方式可以使用 reselect 提供的 createSelector 函数来实现。例如:
-- -------------------- ---- ------- ------ - -------------- - ---- ----------- ----- ------- - ------- -- ----------------- ----- --------- - ------- ------ -- ------------- ------ ----- ---------- - --------------- --------- ----------- ----------- ------- -- ------------------ --
五、Selector 应该根据需要可以接受 props 在某些情况下,我们需要基于组件的 props 属性对 state 进行过滤,比如说被选中的用户的 ID。在这种情况下,我们需要在 Selector 中传入 props 参数,以便作为参数使用。
举个例子,假设我们的 redux store 包含一个 users 对象,每个用户有一个 id、 name 和 email 属性。让我们先定义一个简单的 Selector 用来选择属于当前用户的用户信息:
-- -------------------- ---- ------- ------ - -------------- - ---- ----------- ----- -------- - ------- -- ----------------- ----- ---------------- - ------- ------ -- ------------- ------ ----- ----------------- - --------------- ---------- ------------------ ------- ------- -- -------------- --
这个 Selector 接收 state 和组件属性作为参数,并将它们结合在一起以返回所需的用户信息。
六、使用 memoization 和 reselect 优化代码
Selector 是可以重复使用的,它将为同一组组件渲染生成相同的结果。通过合理使用 memoization 和 reselect,可以减少获取 state 并生成结果的次数,从而通过提高性能、减少代码和可维护性来优化代码。
举个例子,如果我们有一个组件需要使用每一位用户的姓氏,我们可以如下定义 Selector:
import { createSelector } from 'reselect'; const getUsers = (state) => state.users.byId; export const selectSurnames = createSelector( getUsers, (users) => users.map((user) => user.surname), );
这个例子中,getUsers 函数是非负载 Selector。这意味着对于同一个状态树部分,我们会对该函数多次执行。但是,在使用 reselect 和 memoize 时,每个用户的名称只需要在初始渲染时进行一次计算,然后将其缓存起来,就可以避免多次计算。
七、Selector 的最佳实践
Selector 应该返回一个函数。
Selector 不能修改 state,否则会导致意外和难以诊断的错误。
Selector 应该保持简单和可组合,并努力与组件库保持一致。
Selector 应该返回尽可能少的内容,这可以通过使用适当的转换来实现。
Selector 应该只依赖于它所依赖的 state 的子集。
Selector 应该避免使用默认参数,因为这会导致在缓存中使用重复的值。
Selector 应该只在组件嵌套深度超过两个时保留使用。
八、总结 在 Redux 应用中,使用 Selector 可以使代码更高效、可读性更强。我们可以通过 reselect 库和 memoization 来提高性能,并根据需要接受组件的属性。然而,我们需要遵循一些最佳实践,例如避免对 complete state tree 进行计算和保持 Selector 的简单性和可组合性。同时,我们还需要遵循合适的实践,以便提高代码可维护性和可读性。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/64748336968c7c53b01de843