use-context-selector

by dai-shi

React useContextSelector hook in userland

358 Stars 6 Forks Last release: Not found MIT License 111 Commits 19 Releases

Available items

No Items, yet!

The developer of this repository has not created any items for sale yet. Need a bug fixed? Help with integration? A different license? Create a request here:

use-context-selector

CI npm size

React useContextSelector hook in userland

Introduction

React Context and useContext is often used to avoid prop drilling, however it's known that there's a performance issue. When a context value is changed, all components that useContext will re-render.

useContextSelector is proposed. While waiting for the process, this library provides the API in userland.

Install

npm install use-context-selector

Usage

import React, { useState } from 'react';
import ReactDOM from 'react-dom';

import { createContext, useContextSelector } from 'use-context-selector';

const context = createContext(null);

const Counter1 = () => { const count1 = useContextSelector(context, v => v[0].count1); const setState = useContextSelector(context, v => v[1]); const increment = () => setState(s => ({ ...s, count1: s.count1 + 1, })); return (

Count1: {count1} +1 {Math.random()}
); };

const Counter2 = () => { const count2 = useContextSelector(context, v => v[0].count2); const setState = useContextSelector(context, v => v[1]); const increment = () => setState(s => ({ ...s, count2: s.count2 + 1, })); return (

Count2: {count2} +1 {Math.random()}
); };

const StateProvider = ({ children }) => { const [state, setState] = useState({ count1: 0, count2: 0 }); return ( <context.provider value="{[state," setstate> {children} </context.provider> ); };

const App = () => ( );

ReactDOM.render(, document.getElementById('app'));

Technical memo

React context by nature triggers propagation of component re-rendering if a value is changed. To avoid this, this library uses undocumented feature of

calculateChangedBits
. It then uses a subscription model to force update when a component needs to re-render.

API

createContext

This creates a special context for

useContextSelector
.

Parameters

  • defaultValue
    any

Examples

const PersonContext = createContext({ firstName: '', familyName: '' });

Returns React.Context

useContextSelector

This hook returns context selected value by selector. It will only accept context created by

createContext
. It will trigger re-render if only the selected value is referentially changed.

Parameters

  • context
    React.Context
  • selector
    Function

Examples

const firstName = useContextSelector(PersonContext, state => state.firstName);

Returns any

useContext

This hook returns the entire context value. Use this instead of React.useContext for consistent behavior.

Parameters

  • context
    React.Context

Examples

const person = useContext(PersonContext);

Returns any

useContextUpdate

This hook returns an update function that accepts a thunk function

Use this for a function that will change a value.

Parameters

  • context

Examples

import { useContextUpdate } from 'use-context-selector';

const update = useContextUpdate(); update(() => setState(...));

BridgeProvider

This is a Provider component for bridging multiple react roots

Parameters

  • props
    Object
    • props.context
      React.Context
    • props.value
      any
    • props.children
      React.ReactNote

Examples

const valueToBridge = useContext(PersonContext);
return (
  
    
      {children}
    
  
);

Returns React.ReactElement

Limitations

  • In order to stop propagation,
    children
    of a context provider has to be either created outside of the provider or memoized with
    React.memo
    .
  • Provider trigger re-renders only if the context value is referentially changed.
  • Context consumers are not supported.
  • The stale props issue can't be solved in userland. (workaround with try-catch)

Examples

The examples folder contains working examples. You can run one of them with

PORT=8080 npm run examples:01_minimal

and open http://localhost:8080 in your web browser.

You can also try them in codesandbox.io: 01 02

Related projects

We use cookies. If you continue to browse the site, you agree to the use of cookies. For more information on our use of cookies please see our Privacy Policy.