“重新选择”与“ React and Redux”对“记忆一号”

时间:2018-10-15 06:22:09

标签: reactjs redux react-redux memoization reselect

我正在尝试通过React在我的工作流中使用某种形式的备忘录,并且我正在寻找最好的,最重要的“最简单” 解决方案与我的工作流集成,其中包括{ {1}}。

我碰到了很多关于备忘录的文章,其中一些文章展示了“ memoize-one”的用法,并将其作为最快和最容易上手的方法,还有一些甚至没有提及它并谈论“重新选择”。

我只想知道哪个更好,最简单以及应该投资哪个。

3 个答案:

答案 0 :(得分:7)

两个返回一个函数,该函数接受给定数量的参数返回值

getA(arg1, arg2, arg3) // Returns a value

差异在于该函数被调用时在幕后发生的事情。

记忆一遍

  • 收集提供的参数
  • 将参数与上一次调用(===)中提供的参数进行比较
  • 参数相同的:返回缓存的结果
  • 参数不相同:重新评估结果函数并返回

重新选择

  • 收集提供的参数
  • 运行一组inputSelectors函数,为他们提供收集的参数
  • 收集inputSelectors返回值
  • 比较inputSelectors返回值和上一次调用(===)中获得的值
  • 相同的:返回缓存的结果
  • 不同:重新评估结果函数并返回

结论

memoize-one是基于值的备忘录实用程序:记忆是对提供的参数的值执行的。

reselect在其顶部添加了另一个评估层:在一组inputSelectors函数的结果上,不对参数值执行 memoization ,但是 strong>接受了这些初始参数。

这意味着reselect选择器很容易组合,因为每个inputSelectors可以是另一个reselect选择器。

答案 1 :(得分:3)

我还没有使用过重选功能,但是当我想从渲染中的道具中计算出一些东西时,memoize-one对我非常有用。对于在道具上进行昂贵的操作(如映射大型阵列)而言,这是一个很好的模式,该道具可能会随时间变化,但在某些重新渲染时可能不会变化。它确保仅在输入发生更改时才重新计算渲染中使用的昂贵操作。它还避免了必须使用诸如getDerivedStateFromProps之类的生命周期方法(如果可以从props计算出来的话,它可能不应该处于状态)。

import memoize from 'memoize-one'

class Example extends Component {

  mapList = memoize(
    (list) => list.map(item => ({text: item.text}))
  )

  render() {
    // if this.props.list hasn't changed since the last render
    // memoize-one will re-use the last return value from cache
    const mappedList = this.mapList(this.props.list)

    return (
      ...
    )
  }
}

请记住,在大多数情况下,相对于使用静态类变量,您将需要将备忘录化的函数附加到组件实例。这样可以防止组件的多个实例重置彼此的记忆键。

答案 2 :(得分:1)

我建议使用reselect,因为它是专门为与React / Redux一起使用而设计的。 memoize-one更像是通用的记忆库。

使用重新选择真的很容易,它只是包装了选择器:

import { createSelector } from 'reselect';

const shopItemsSelector = state => state.shop.items;

// without reselect
const subtotalSelector = state => {
  const items = shopItemsSelector(state);
  return items.reduce((acc, item) => acc + item.value, 0);
}

// with reselect
const subtotalSelector = createSelector(
  shopItemsSelector, // list the selectors you need
  items => items.reduce((acc, item) => acc + item.value, 0) // the last argument is actual selector
)