Redux 中使用 Reselect 库实现数据缓存

在 Redux 应用中,我们通常需要根据 state 中的数据计算出一些派生数据,比如过滤、排序等。这些派生数据可以使用计算属性(computed property)来实现,但是每次使用计算属性都会重新计算,可能会影响性能。为了避免重复计算,我们可以使用 Reselect 库来实现数据缓存。

Reselect 简介

Reselect 是一个用于创建可记忆的(memoized)选择器函数的库。选择器函数接收 state 作为输入,并返回派生数据。Reselect 的主要作用是缓存选择器函数的计算结果,避免重复计算。

Reselect 的主要特点包括:

  • 可记忆的:相同的输入会返回相同的输出,避免重复计算。
  • 高效的:只有当输入数据发生变化时,才会重新计算。
  • 灵活的:可以组合多个选择器函数,创建更复杂的派生数据。

Reselect 的使用

使用 Reselect 需要先安装该库:

--- ------- --------

然后,我们可以创建一个选择器函数,用于计算派生数据。例如,我们有一个 state,包含一个列表和一个过滤条件:

----- ----- - -
  ----- -
    - --- -- ----- ------- --
    - --- -- ----- ----- --
    - --- -- ----- --------- --
  --
  ------- ----
--

我们希望根据过滤条件筛选列表中的元素,并返回筛选后的结果。可以使用下面的代码创建一个选择器函数:

------ - -------------- - ---- -----------

----- ------- - ----- -- -----------
----- --------- - ----- -- -------------

----- ----------- - ---------------
  --------- -----------
  ------ ------- -- -
    ------ ---------------- -- ----------------------------
  -
--

在上面的代码中,我们使用 createSelector 创建了一个选择器函数 getFiltered。这个函数接收两个输入参数 getList 和 getFilter,分别用于获取列表和过滤条件。在计算派生数据时,我们使用 filter 方法筛选列表中的元素,并返回结果。

使用选择器函数时,我们可以像调用普通函数一样调用它:

----- ------------ - -------------------
--------------------------
-- ------- -- --- -- ----- ------- --

在上面的代码中,我们传入 state 参数调用 getFiltered 函数,并获取筛选后的结果。

Reselect 的优化

使用 Reselect 可以避免重复计算,提高应用性能。但是,为了实现最佳性能,我们需要遵循一些优化原则。

原则一:选择器函数应该是纯函数

选择器函数应该是纯函数,即相同的输入应该返回相同的输出。这样可以避免因为副作用导致缓存无效。

例如,下面的代码中,选择器函数会改变 state 中的数据,导致缓存无效:

----- ------- - ----- -- -----------
----- --------- - ----- -- -
  ------------ - ---- -- ------ ----- ----
  ------ -------------
--

----- ----------- - ---------------
  --------- -----------
  ------ ------- -- -
    ------ ---------------- -- ----------------------------
  -
--

为了避免这种情况,我们应该将选择器函数设计成纯函数:

----- ------- - ----- -- -----------
----- --------- - ----- -- -------------

----- ----------- - ---------------
  --------- -----------
  ------ ------- -- -
    ----- ------------ - ---------------- -- ----------------------------
    ------ -------------
  -
--

在上面的代码中,我们不再改变 state 中的数据,避免了副作用。

原则二:选择器函数应该是高效的

选择器函数应该是高效的,即只有当输入数据发生变化时,才会重新计算。为了实现这一点,我们应该尽量避免在选择器函数中进行复杂的计算,而是将复杂计算拆分成多个选择器函数,然后组合起来使用。

例如,我们有一个 state,包含一个列表和一个排序方式:

----- ----- - -
  ----- -
    - --- -- ----- -------- ---- -- --
    - --- -- ----- ------ ---- -- --
    - --- -- ----- ---------- ---- -- --
  --
  ------- -------
--

我们希望根据排序方式对列表进行排序,并返回排序后的结果。可以使用下面的代码创建选择器函数:

------ - -------------- - ---- -----------

----- ------- - ----- -- -----------
----- --------- - ----- -- -------------

----- --------------- - ---------------
  ----------
  ---- -- -
    ------ ------------------ -- -- ------------------------------
  -
--

----- -------------- - ---------------
  ----------
  ---- -- -
    ------ ------------------ -- -- ----- - -------
  -
--

----- --------- - ---------------
  ----------------- --------------- -----------
  -------------- ------------ ------- -- -
    ------ ------ --- ------ - ------------ - ------------
  -
--

在上面的代码中,我们定义了三个选择器函数:getSortedByName、getSortedByAge 和 getSorted。getSortedByName 和 getSortedByAge 分别用于按照名称和年龄排序列表。getSorted 用于根据排序方式选择使用哪个排序函数。

在使用选择器函数时,我们可以像下面这样调用它:

----- ---------- - -----------------
------------------------
-- ------- -- --- -- ----- -------- ---- -- -- - --- -- ----- ------ ---- -- -- - --- -- ----- ---------- ---- -- --

在上面的代码中,我们传入 state 参数调用 getSorted 函数,并获取排序后的结果。

总结

Reselect 是一个用于创建可记忆的选择器函数的库,可以避免重复计算,提高应用性能。使用 Reselect 需要遵循一些优化原则,包括选择器函数应该是纯函数,选择器函数应该是高效的。在实际使用中,我们可以将复杂计算拆分成多个选择器函数,然后组合起来使用。

来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/65c98a01add4f0e0ff3599af