• Stars
    star
    129
  • Rank 279,262 (Top 6 %)
  • Language
    JavaScript
  • License
    MIT License
  • Created almost 7 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

🧠 React memoization library we all deserve

react-memoize 🤯 🧠


memoize

Build status


7kb MobX-level memoization library, which tracks all the arguments you are really depends on.

  • It is not so fast, as reselect, but could handle more cases, and works out of the box.
  • It is not so fast, but much faster, than VDOM tree comparison you will face in case of render trashing.
  • It contain 3 types of memoziation to handle all possible cases.

Uses memoize-state underneath, providing the same magic for get as immer provided to set.

Works fine in all browsers including IE11.

Just write code as you want. It it will be properly memoized.

This is declarative component memoization for React! Based on Dan Abramov's tweet Could change the way you did componentWillReceiveProps, could replace getDerivedStateFromProps, could make things better.

IE11+, React 15 and React 16.3 compatible.

  • Memoize - to create declarative memoized selection.
  • MemoizedFlow - to create declarative memoized flow.
  • MemoizeContext - to create memoized selector from context(or any Consumer).
  • MemoizedRender - to create a render, memoized by a value provided.

Memoize, MemoizedFlow, MemoizeContext accepts one or more functions to select or transform incoming data, and provide result to a function-as-child.

MemoizedRender is memoizing the function-as-child itself.

What is the difference between React-memoize and React.memo? Memo is a "PureComponent", Memoize is more about accurate memoization based on the real props consumption. React-memoize is about "calculation" memoization

Memoize

 import Memoize from 'react-memoize';
 
 <Memoize
   prop1 = "theKey"
   state = {this.state}
   // values from above will be provided to compute function
   compute={({prop1, state}) => heavyComputation(state[prop1])} // Memoize tracks WHAT you are doing 
   pure // Memoize will be a pure component itself
  >
  { result => <Display>{result}</Display>}
  </Memoize>

There is only one prop - compute, all others will be passed inside. Memoize get compute function, add passes all the other props to it, streaming result to the render prop.

If pure prop is set ReactMemoize wil behave as PureComponent, and not update children when could not.

Flow

getDerivedStateFromProps gives you ability to derive a new state from props, while componentDidUpdate enables you to react to the state changes.

MemoizedFlow is getDerivedStateFromState. Following example react to the state changes, allowing to change ordering of rows and applies a pagination.

"The Flow" is safe and performant way to form something from something, and rebuilt then the time calls.

import {MemoizedFlow} from 'react-memoize';

class SortablePageableTable extends Component {
    state = {
    page:0,
    perPage:10,
    filter: I => I
    };
    
    onSortChange = (order) => this.setState(order)
    onPageChange = page => this.setState(page);
    
    render () {
    return (
          <MemoizedFlow 
          input={{...this.props, ...this.state}}
          flow={[
            // will react on rows or filter change
            ({rows, filter}) => ({rows: list.filter(filter)}),
            // will react on rows(from step1) change or order
            ({rows, order}) => ({rows: list.slice().sort(order)}), // !! clone array before sort
            // will react on rows and pagination changes
            ({rows, page, perPage}) => ({rows: list.slice(page*perPage, (page+1)*perPage)}),
            // will react on something else, not related
            ({rain, bows}) => ({rainbows: rain+bows, rain: null, bows: null })
            ]}
          >
            {output => <Table {...output} onSortChange={this.onSortChange} onPageChange={this.onPageChange}/>}
          </MemoizedFlow>
    }
}

<SortablePageableTable rows = {tableRows} />

First step is getting input, and each following is reading from a value provided before, spreading own result over it. Until the last step will be reached, and output will be provided to render prop.

Each step is memoized, as usual, and will always reuse value from the steps before.

MemoizeContext

React memoize also provides component to select and memoize data from React16 context, or any other component which will pass some values into renderProp.

import {MemoizeContext} from 'react-memoize';

<Context.Provider value={{prop1: 1, prop2: 2, prop3: 3}}>
    <MemoizeContext consumer={Context.Consumer} selector={select}>
      {values => <Render {...values} />}
    </MemoizeContext>
</Context.Provider>

consumer could be any "context"-compatible Component - React.context, create-react-context, unstated, react-copy-write. All the additional props will be passed down to consumer.

It is better to explain using example.

<MemoizeContext consumer={Consumer} prop1={1} anotherProp={3} selector={select}> />

// will result

<Consumer prop1={1} anotherProp={3}>
{ contextValues => <ReactMemoize {...contextValues} compute={selector}>...</ReactMemoize>}
</Consumer>

This is like Redux without dispatching. State in context, selector aka mapStateToProps, and magic memoization in between.

See it in action -> https://codesandbox.io/s/xjz5y3wzrz 🛠

MemoizedRender

MemoizedRender is mostly usable with Context API

import {MemoizedRender} from 'react-memoize';

<Context.Provider value={{prop1: 1, prop2: 2, prop3: 3}}>
    <MemoizedRender consumer={Context.Consumer}>
      {values => <Render {...select(values)} />}
    </MemoizedRender>
</Context.Provider>

Or, the better example (from react-copy-write)

const UserAvatar = ({ id }) => (
  <MemoizedRender consumer={State.Consumer}>
    {state => (
      <div className="avatar">
        <img src={state.users[id].avatar.src} />
      </div>
    )}
  </MemoizedRender>
);

While react-copy-write declares that _ The problem with this is that whenever any value in state changes, UserAvatar will be re-rendered, even though it's only using a single property from a single, nested object._ This example will work, as long MemoizedRender will track used keys, and perform update only when necessary.

It is also possible to provide value as a prop

<MemoizedRender value={originalValue}>
  {values => <Render {...select(values)} />}
</MemoizeContext>

MemoizedRender memoizes "render" as a whole. This is absolute pure component. Be carefull. Might be not 100% compatible with async rendering if you pass values you were provided down the tree, as long async accessed keys are not tracked. Thus - MemoizedRender may not react to changes in them.

About

React-memoize uses memoize-state underneath to perform MobX like memozation and achive the maximal minimal level of memoization cache misses. Sounds a bit strange, but this mean - react-memoize will try to preserve the current state at all costs. From 10% to 50% "more" in comparison.

In all the cases only ONE! result is memoized. The goal of the component is to cut off updates.

For example:

  • recomputation will be made only when stateSubKey is changed
 <Memoize
   state = {this.state}   
   compute={({state}) => soSomethingWith(state.stateSubKey)}
  >
  { result => ....}
  </Memoize>
  • recomputation will be made only when used prop is changed
 <Memoize
   usedProp = {1}   
   unusedProp = {2}
   compute={({usedProp}) => soSomethingWith(usedProp)}
  >
  { result => ....}
  </Memoize>
  • recomputation will be make only when item count changes, value of any item or text of items passed thought the filter.
 <Memoize
   list = {this.state.list}   
   compute={({list}) => list.filter(item => item.value).map(item => item.text)}
  >
  { result => ....}
  </Memoize>

The same magic as in beautiful-react-redux, kudos to memoize-state library.

PS: For systems without Proxy support memoize will use memoize-one

Licence

MIT

More Repositories

1

react-focus-lock

It is a trap! A lock for a Focus. 🔓
JavaScript
1,092
star
2

react-imported-component

✂️📦Bundler-independent solution for SSR-friendly code-splitting
TypeScript
651
star
3

react-remove-scroll

Removes and disables 📜in a "React" way
TypeScript
611
star
4

rewiremock

The right way to mock dependencies in Node.js or webpack environment.
JavaScript
442
star
5

memoize-state

The magic memoization for the State management. ✨🧠
JavaScript
324
star
6

react-focus-on

🎯 Solution for WAI ARIA compatible modal dialogs or full-screen tasks, you were looking for
TypeScript
271
star
7

use-callback-ref

🤙The same useRef, but it will callback
TypeScript
265
star
8

devolution

🦎 -> 🦖A de-evolution gun for your bundle!
JavaScript
189
star
9

react-prerendered-component

🤔Partial hydration and caching in a pre-suspense era
TypeScript
164
star
10

react-locky

"🔒-y" – Asgardian God of Event Scoping 📦, Scroll Locking 📜, Silence Casting 🙊
JavaScript
145
star
11

focus-lock

Gotcha! A11y util for scoping a focus.
TypeScript
139
star
12

vue-focus-lock

It is a trap! A lock for a Focus. A11y util for scoping a focus.
Vue
135
star
13

react-shallow-context

☘️A speed optimization for a Context API
TypeScript
119
star
14

faste

Table based 📦 Finite State Machine 🤖
TypeScript
119
star
15

used-styles

📝All the critical styles you've used to render a page.
TypeScript
115
star
16

use-sidecar

Another way to code splitting
TypeScript
94
star
17

stylelint-semantic-groups

Opinionated rule ordering
TypeScript
92
star
18

beautiful-react-redux

Redux 🚀, Redux 🤘, Redux 🔥 - and the magic optimization
JavaScript
89
star
19

recondition

🤷‍♂️ Declarative render prop based Conditions
TypeScript
77
star
20

proxyequal

There is a bit more smart way to compare things, than a shallow equal.
JavaScript
72
star
21

kashe

A memoization library based on weakmaps. 🤯 Sometimes cache is kashe
TypeScript
63
star
22

react-remove-scroll-bar

Remove document scroll bar. Nothing more
TypeScript
59
star
23

react-scroll-locky

📜🔒 – React full-cream "anti-scroll" library, you were looking for
TypeScript
56
star
24

restate

A redux fractal state library 🕷
JavaScript
55
star
25

dom-focus-lock

It's a Trap! A11y util for scoping a focus.
JavaScript
52
star
26

react-event-injector

💉React way to addEventListener
TypeScript
45
star
27

React-stroller

🚶‍♂️Scroll as you Stroll - the most native custom scrollbars ever made
TypeScript
45
star
28

react-remock

Get any Component replaced. Anywhere. 🛠♻️
TypeScript
44
star
29

multiple-entry-points-example

a npm library with multiple entry points, all typed, all shipped in cjs/esm versions
TypeScript
43
star
30

react-reflexible

🐍 Responsible solution in a flexible form.
TypeScript
43
star
31

aria-hidden

🗣Cast aria-hidden to everything, except...
TypeScript
42
star
32

why-did-you-update-redux

Patch Redux to discover unnecessary re-renders
JavaScript
41
star
33

jsx-compress-loader

⚛️JSX optimisation loader to reduce size of React application
JavaScript
40
star
34

holistic-image

Wholesome image management
TypeScript
37
star
35

theKashey

This is me! 👨‍🔧And all the things I've done. 🧙🏻‍♂️
36
star
36

eslint-plugin-relations

Controls relationships between folders and packages 👩‍💻🤝👮🏻‍♂️
TypeScript
32
star
37

react-gearbox

⚙️📦 Gearbox - Renderless state provisioning and composition
TypeScript
30
star
38

styled-components-mixins

Use popular frameworks with Styled Components
JavaScript
30
star
39

react-on-time

Renderless composable ⏰timers and ⏱intervals
TypeScript
27
star
40

runtime-compress-loader

babel and typescript "runtime" helpers optimization loader
JavaScript
23
star
41

react-queue

⛓ Declarative task scheduler
TypeScript
23
star
42

plimited

👽Promise-based Resource Pool
TypeScript
15
star
43

flow-meter

http(s/2) chunked response meter
TypeScript
14
star
44

react-style-singleton

Simple stylesheet manager for good libraries
TypeScript
14
star
45

use-callback-state

The same `useState`, but it will callback - https://codesandbox.io/s/use-callback-state-fcxtb
TypeScript
14
star
46

require-control

Get the full control over the nodejs module system.
JavaScript
14
star
47

webpack-imported

📝stats-webpack-plugin and 💩webpack-flush-chunks had a baby!
TypeScript
13
star
48

react-rename

Create a renamed duplicate for any Component. For the Fun, and Debug ( sure 🤞)
TypeScript
11
star
49

ts-referent

🤖 project references made not by humans
TypeScript
9
star
50

partial-mock

A solution for ⬆️over and ⬇️under mocking
TypeScript
9
star
51

storybook-include

Folder based storybook configuration for monorepos
TypeScript
9
star
52

react-nyan-stroller

🐈🏳️‍🌈🏳️‍🌈🏳️‍🌈 Nyanyanyanyanyanyanya! (In form of custom scroll bar) https://codesandbox.io/s/j2l71rrxw
TypeScript
9
star
53

quadLoader

загрузчик по пирамиде
8
star
54

react-imported-library

✂Code-split any library using renderProps!
TypeScript
8
star
55

yarn-unlock-file

🧶🔓 keeping things up to date.
TypeScript
8
star
56

read-story-later

Defer storybook's story execution.
JavaScript
7
star
57

react-push-channel

🎈Context is to drill props down. React Push Channel to drill props up.
TypeScript
7
star
58

useReselect

hooks friendly reselect
TypeScript
6
star
59

address-complete

What are you looking for?
JavaScript
6
star
60

idea-exclude

Some your .ideas better be excluded
TypeScript
6
star
61

search-trie

Yet another O(n) trie. This time just and only for string search.
TypeScript
6
star
62

jest-typed-mock

Be safe!. And use the force of TS/Flow to make mocks better.
JavaScript
6
star
63

tileLoader

тайловый загрузчик для yandex2
5
star
64

react-loadable-library

Code-split any library using renderProps!
TypeScript
5
star
65

react-svg-atlas

Combine, isolate, skyrocket the SVG
JavaScript
4
star
66

the-country-names

How to explain the world? Split it into pieces and name the each one.
JavaScript
4
star
67

wipeWebpackCache

JavaScript
3
star
68

css-to-js-loader

Transforms your CSS to the `real` JS
JavaScript
3
star
69

package-self

Place yourself in the right place.
JavaScript
3
star
70

postcss-to-js

A way to create javascript code from css
JavaScript
3
star
71

react-side-channel

To the RenderProps and back.
TypeScript
3
star
72

react-dom-reflection

🔨React meets DOM-API
TypeScript
3
star
73

with-known-usage

👁ES5/ES6 compatible object key usage tracker
TypeScript
3
star
74

proxyquire-webpack-alias

Modification of proxyquire to work with webpack aliases. Proxies commonjs require/es6 import in order to allow overriding dependencies during testing.
JavaScript
3
star
75

restructor

Change your mind 🤯. Face naming standards 🤦‍♀️. Easily rename JavaScript modules 🧙🏻‍♂️.
JavaScript
3
star
76

scan-directory

Multithreaded nodejs directory scan
JavaScript
3
star
77

what-did-i-load

puppeteer based resource investigation
JavaScript
2
star
78

react-fiber-walker

Walks live React Fiber
TypeScript
2
star
79

function-double

Stand in for a function
JavaScript
2
star
80

vue-demi-focus-lock

Vue
2
star
81

derive-svg-components

Derive React components from SVG base
TypeScript
2
star
82

y2FastOverlay

Один из варианта получения скорости при работе с оверлеями напрямую
2
star
83

wipeNodeCache

JavaScript
2
star
84

compare-module-exports

JavaScript
2
star
85

flow-meter-ui

https://flow-meter-ui.vercel.app/
HTML
2
star
86

storybook-addon-poleaxe

a11y (poly) axe
TypeScript
2
star
87

4D

old school C++ stuff
C++
1
star
88

hoist-react-statics

A little helper for a better HOCs
JavaScript
1
star
89

rewiremock-simple-example

testing stuff
JavaScript
1
star
90

maps

различные околокартографические примеры
1
star
91

immutable-changes

Get will found the root change!
JavaScript
1
star
92

gulp-html-prefix

Simple gulp plugin to prefix classNames
JavaScript
1
star