Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"Reselect" VS "Memoize-One" with "React and Redux"

I'm trying to use some kind of memoization in my workflow with React, and I'm searching for the best and most importantly the "easiest" solution to integrate with my workflow that includes React and Redux.

I came across many articles talking about memoization in general and some demonstrate the use of "memoize-one" and brace it as the fastest and easiest to get up and running with, and others don't even mention it and talk about "reselect".

I just want to know which is better and easiest and which should I invest in.

like image 203
Ruby Avatar asked Oct 15 '18 06:10

Ruby


3 Answers

Both libraries return a function which accepts a given numbers of arguments and returns a value:

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

The difference lays in what happens under the hoods when the function is called.

memoize-one

  • collect provided arguments
  • compare arguments with the ones provided in previous call (===)
  • arguments are the same: return cached result
  • arguments are NOT the same: re-evaluate result function and return

reselect

  • collect provided arguments
  • run a set of inputSelectors function providing them with the collected arguments
  • collect inputSelectors return values
  • compare inputSelectors return values with the ones obtained in previous call (===)
  • values are the same: return cached result
  • values are NOT the same: re-evaluate result function and return

Conclusions

memoize-one is a value-based memoize utility: memoization is performed over the value of provided arguments.

reselect adds a further evaluation layer on top of it: memoization is NOT performed over arguments values BUT over the results of a set inputSelectors functions fed with those initial arguments.

It means that reselect selectors are easily composable since each inputSelectors can be another reselect selector.

like image 167
Andrea Carraro Avatar answered Sep 25 '22 13:09

Andrea Carraro


I haven't used reselect, but memoize-one works great for me when I want to calculate something from props inside render. This is a great pattern for doing an expensive operation, like mapping a large array, on props that may change over time but also may not change on some re-renders. It ensures an expensive operation used in render is re-computed only when the inputs change. It also avoids having to use lifecycle methods like getDerivedStateFromProps (if it can be calculated from props, it probably shouldn't be on state).

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 (
      ...
    )
  }
}

Keep in mind, in most cases, you’ll want to attach the memoized function to a component instance vs. using a static class variable. This prevents multiple instances of a component from resetting each other’s memoized keys.

react memoization reactjs

like image 44
Carey Avatar answered Sep 25 '22 13:09

Carey


I suggest to use reselect, since it was specifically designed to use with React/Redux. memoize-one is more like a general purpose memoization library.

It's really easy to use reselect, it just wraps your selectors:

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
)
like image 40
Dávid Molnár Avatar answered Sep 24 '22 13:09

Dávid Molnár