react-lightning-context
This is a performant and simple react context
A super performant lightning fast context library that only re-renders what has changed and nothing else. This library is a drop in replacement of the official React Context
.
When building web apps at scale one of the main problems is performance over time. When you have 20+ multiple teams contributing to a same code base it is impossible to not hit this bottleneck. This library tries to mitigate some of this problem by providing a Context API
that is reliant ant performant. It tries to avoid the un-necessary re-renders problem that the React Context
has by only re-rendering what is upmost needed. As a result performance can be boosted dramatically.
This is NOT a state management library. Just a performant React Context
replacement. You can also mix this up with redux for example and get a full redux experience but this is outside the scope of this library.
How to install
yarn add react-lightning-context
API Documentation
Name | Supported ? | Description |
---|---|---|
React.createContext renamed to createContext |
Yes | It is how we create the context we use createContext instead of React.createContext |
Context.Provider |
Yes | |
Class.contextType |
No | |
Context.displayName |
Yes | |
Context.Consumer |
Yes | A way of consuming a context value using components. |
useContext |
Yes | A way of consuming a context slices (one or many) using hook. Similar to useContext |
useContextSlice |
Yes | A way of consuming a context slice using hook. Similar to useContext |
Context.Mutator |
New | A component that provides a way of mutating the value of the context |
useContextMutator |
New | A Hook that provides a way of mutating the value of the context |
useContextSliceMutator |
New | A Hook that provides a way of mutating only one slice of the context |
createContext
It follows a similar api that the React.Context
provides. It only differs that we have a second parameter with configuration options.
Parameters | Types | Required | Values | |
---|---|---|---|---|
First Parameter | defaultValue |
Any | Yes | The default value to initialize the Context |
Second Parameter | Options |
Object | No | |
Options.waitBeforeUpdate |
Boolean | Default: false. This helps when you have a very volatile Context value, that is constantly mutating. This helps by debouncing the updates so you can update the components less times having a similar effect to the concurrentMode effect. |
It returns the Provider, Consumer, Mutator
components
Example
const Context = createContext({ value: 'test' });
const Context = createContext({ value: 'test' }, { waitBeforeUpdate: true });
Context.Provider
Properties | Type | Required | Description |
---|---|---|---|
initialValue |
any | No | Defaults to the initialValue if passed, note that once the initialValue is set it won't be refreshed if updated |
Context.Provider Example
import { createContext } from 'react-lightning-context';
const Context = createContext({ value: 'test' });
const TopLevelExperience = () => {
return <Context.Provider>// ... your experience</Context.Provider>;
};
Context.Provider Example with initialValue
import { createContext } from 'react-lightning-context';
const Context = createContext({ value: 'test' });
const TopLevelExperience = () => {
return <Context.Provider initialValue={{...}}>// ... your experience</Context.Provider>;
};
Context.Consumer
This need to be nested inside a Provider
component. Same as React.Context
it uses the function render pattern and it execution a function when it need to be render.
Properties | Type | Required | Description |
---|---|---|---|
slices |
Array< String > | Yes | Properties from the Context.value that you want to listen to. It can be nested |
It returns a function that is executed passing a mapped object with the binding
Context.Consumer Example
import { createContext } from 'react-lightning-context';
const Context = createContext({ value: { first: 1, second: 2 } });
const TopLevelExperience = () => {
return <Context.Provider>
<Context.Consumer slices={['value.first', 'value.seconds']}>
{
(values) => //... anything to render
}
</Context.Consumer>
</Context.Provider>;
};
Return value example
if slices is ['value.first', 'value.seconds']
the render function that will execute is
({ value: {
first: 123,
seconds: 333
} }) => //...anything to render
useContext
Same as Consumer
but as a Hook api (similar to the useContext
hook)
Properties | Type | Required | Description |
---|---|---|---|
Object.slices |
Array |
Yes | Properties from the Context.value that you want to listen to. It can be nested |
Context |
createContext returned object |
Yes | The context you are using |
import { useContext } from 'react-lightning-context';
const result = useContext({ slices: [...] }, Context);
Return value example for the Hook
if slices is ['value.first', 'value.seconds']
the render function that will execute is
const {
value: {
first: 123,
seconds: 333
}
} = useContext({ slices: ['value.first', 'value.seconds'] }, Context)
useContextSlice
Same as Consumer
but as a Hook api (similar to the useContext
hook)
Properties | Type | Required | Description |
---|---|---|---|
slice |
String | Yes | Properties from the Context.value that you want to listen to. It can be nested |
Context |
createContext returned object |
Yes | The context you are using |
import { useContextSlice } from 'react-lightning-context';
const sliceFromContext = useContextSlice('property', Context);
Context.Mutator
This need to be nested inside a Provider
component. This is a component that provides a callback to update the internal context value. It uses the function render pattern and it execute a function when it need to be render passing the callback. No props are available.
It returns a function that is executed passing a callback function called setContextValue
. This will updates the internal values and ONLY re-render what has changed and has someone listening.
Example calling setContextValue
The value parameter is the current context value
setContextValue((value) => {
return {
...value,
...yourChangeGoesHere,
};
});
setContextValue Example
import { createContext } from 'react-lightning-context';
const Context = createContext({ value: { first: 1, second: 2 } });
const TopLevelExperience = () => {
return <Context.Provider>
<Context.Mutator>
{
({ setContextValue }) => //... anything that want to use setContextValue
}
</Context.Mutator>
</Context.Provider>;
};
useContextMutator
Same as Context.Mutator
but as a Hook.
Properties | Type | Required | Description |
---|---|---|---|
Context |
createContext returned object |
Yes | The context you are using |
import { useContextMutator } from 'react-lightning-context';
const setContextValue = useContextMutator(Context);
Example calling setContextValue from useContextMutator
setContextPropValue((contextValue) => {
// do anything you want
return AnyNewContextValue;
});
useContextSliceMutator
This is same as the useContextMutator
but only mutate one property of the Context value
. As a result no need to merge anything.
Properties | Type | Required | Description |
---|---|---|---|
slice |
String | Yes | The prop you are mutating, can be a nested property too |
Context |
createContext returned object |
Yes | The context you are using |
useContextSliceMutator Example
import { useContextSliceMutator } from 'react-lightning-context';
const setContextPropValue = useContextSliceMutator('object.valueA.valueB', Context);
Example calling setContextPropValue
The propValue parameter is the current context prop value
setContextPropValue((propValue) => {
// do anything you want
return AnyNewPropValue;
});
useContextReducer
This hook allow you to create a reducer to mutating the context value. This is helpful when you have to setup complex logic to update the context value. It is very similar to useReducer
but the affected state is the context value.
Properties | Type | Required | Description |
---|---|---|---|
Object.reducer |
Function(currentValue, action) => nextValue | Yes | |
Context |
createContext returned object |
Yes | The context you are using |
It returns the dispatch function to execute actions in the context value.
useContextReducer Example
import { useContextReducer } from 'react-lightning-context';
function reducer(state, action) {
switch (action.type) {
case 'update':
return { valA: 333, valB: 222, dummy: numberOfRendersA + 1 };
default:
throw new Error();
}
}
const dispatch = useContextReducer(reducer, Context);
How to call it?
dispatch({ type: 'update' });