Git Product home page Git Product logo

react-memoize's Introduction

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

react-memoize's People

Contributors

greenkeeper[bot] avatar joshburgess avatar lucleray avatar thekashey avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

react-memoize's Issues

An in-range update of enzyme-adapter-react-16.3 is breaking the build 🚨

The devDependency enzyme-adapter-react-16.3 was updated from 1.2.0 to 1.3.0.

🚨 View failing branch.

This version is covered by your current version range and after updating it in your project the build failed.

enzyme-adapter-react-16.3 is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.

Status Details
  • ❌ ci/circleci: Your tests failed on CircleCI (Details).

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

An in-range update of eslint-plugin-react is breaking the build 🚨

The devDependency eslint-plugin-react was updated from 7.11.1 to 7.12.0.

🚨 View failing branch.

This version is covered by your current version range and after updating it in your project the build failed.

eslint-plugin-react is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.

Status Details
  • ❌ ci/circleci: Your tests failed on CircleCI (Details).

Release Notes for v7.12.0

Added

Fixed

Changed

Commits

The new version differs by 127 commits.

  • a83d65c Update CHANGELOG and bump version
  • 0c6160e [Dev Deps] update coveralls, babel-eslint, typescript
  • cd6c8e6 [Deps] update resolve
  • d2b5b73 Merge pull request #1828 from alexzherdev/1721-no-typos-create-class
  • e747459 [Tests] remove node 5/7/9, add node 11
  • b33ae84 Merge pull request #1098 from arian/createElement-display-test
  • 84be80a Merge pull request #1824 from alexzherdev/1762-jsx-max-depth-false-positive
  • a442067 Merge pull request #2029 from sstern6/issue1422
  • 7d07c37 Merge pull request #2032 from alexzherdev/jsx-fragments-message
  • 8c6a8e2 Merge pull request #2089 from jomasti/feature/support-react-forwardref-memo
  • 14451d4 Merge pull request #2085 from himynameisdave/issues/2083
  • 8be52c7 πŸ“ Addresses CR comments
  • f7e3121 Merge branch 'master' of https://github.com/yannickcr/eslint-plugin-react into issues/2083
  • 77e3fd0 Merge pull request #2090 from JBallin/no-method-set-state-docs-url
  • 7da9e0d Fix noMethodSetState docsUrl's

There are 127 commits in total.

See the full diff

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

An in-range update of memoize-state is breaking the build 🚨

The dependency memoize-state was updated from 2.0.3 to 2.0.4.

🚨 View failing branch.

This version is covered by your current version range and after updating it in your project the build failed.

memoize-state is a direct dependency of this project, and it is very likely causing it to break. If other packages depend on yours, this update is probably also breaking those in turn.

Status Details
  • ❌ ci/circleci: Your tests failed on CircleCI (Details).

Commits

The new version differs by 2 commits.

See the full diff

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

Use componentDidUpdate instead of getDerivedStateFromProps

Use componentDidUpdate instead of getDerivedStateFromProps to run side-effects?

Currently, one could use selector/flow-step with side-effect, and have to defer any state change he could execute inside, leading to 2 problems.

  1. memoize-state does not properly work with async stuff, concreting usage just after a function call.
  2. Possible double rendering.

An in-range update of @types/react is breaking the build 🚨

The devDependency @types/react was updated from 16.4.14 to 16.4.15.

🚨 View failing branch.

This version is covered by your current version range and after updating it in your project the build failed.

@types/react is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.

Status Details
  • ❌ ci/circleci: Your tests failed on CircleCI (Details).

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

An in-range update of enzyme is breaking the build 🚨

There have been updates to the enzyme monorepo:

    • The devDependency enzyme was updated from 3.5.1 to 3.6.0.

🚨 View failing branch.

This version is covered by your current version range and after updating it in your project the build failed.

This monorepo update includes releases of one or more dependencies which all belong to the enzyme group definition.

enzyme is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.

Status Details
  • ❌ ci/circleci: Your tests failed on CircleCI (Details).

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

An in-range update of react is breaking the build 🚨

There have been updates to the react monorepo:

    • The devDependency react was updated from 16.6.1 to 16.6.2.

🚨 View failing branch.

This version is covered by your current version range and after updating it in your project the build failed.

This monorepo update includes releases of one or more dependencies which all belong to the react group definition.

react is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.

Status Details
  • ❌ ci/circleci: Your tests failed on CircleCI (Details).

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

An in-range update of codecov is breaking the build 🚨


🚨 Reminder! Less than one month left to migrate your repositories over to Snyk before Greenkeeper says goodbye on June 3rd! πŸ’œ πŸššπŸ’¨ πŸ’š

Find out how to migrate to Snyk at greenkeeper.io


The devDependency codecov was updated from 3.6.5 to 3.7.0.

🚨 View failing branch.

This version is covered by your current version range and after updating it in your project the build failed.

codecov is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.

Status Details
  • ❌ ci/circleci: Build Error: Your tests failed on CircleCI (Details).

Commits

The new version differs by 11 commits.

See the full diff

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.