/react-memoized-context

No more extra re-renders when consuming a Context

Primary LanguageJavaScript

react-memoized context

npm version minzip Build Status MIT license

Avoid unnecessary re-renders when consuming partially a React Context.

  • < 1kb GZIP 🔬
  • Tree-shakable 🌴

Motivation

When a component has simple props, using PureComponent/Memo() is a possible solution to avoid extra re-renders from props coming from Context. However, components with complex props might perform worse when using PureComponent. It's in that moment that react-memoized-context rocks. It works like PureComponent/Memo() but it only performs the shallow comparison to props coming from Context.

See a Working Demo showing the benefits of react-memoized-context.

Installing

npm install react-memoized-context --save

Using

A. HOC

import { withMemoizedContext } from 'react-memoized-context';

const FootNote = ({ context, ...otherProps }) => {  
  /*... do stuff with context.name ...*/
}

// Only re-renders FootNote when UserContext.name changes.
const FootNoteContexted = withMemoizedContext(UserContext)(FootNote, ['name']);

B. Component renderProp

import { MemoizedContext } from 'react-memoized-context';

// Only re-renders FootNote when UserContext.name changes.
<MemoizedContext context={ UserContext } memoKeys={ ['name'] }>
    ({ name }) => <FootNote author={ name } />
</MemoizedContext>

C. Hook?

Well... the way React hooks work, it's impossible to directly subscribe to a part of the context value without re-rendering. See React issue #14110

function FootNote() {
  const { name } = useContext(UserContext);

  // FootNote re-renders when UserContext value changes, even if name is the same.
  <FootNote author={ name } />
}

Workaround

Use an extra hook useMemo as a wall between the Context part and the rest of the Component children. See React issue #15156.

function FootNote() {
  const { name } = useContext(UserContext);

  // Only re-renders FootNote when name is updated.
  return useMemo(() => (
    <FootNote author={ name } />
  ), [name])
}

See full Documentation with Demo.


Contributing

  • Development: yarn docz:dev
  • Testing: yarn test

Feel free to open an issue or PR.