# react-binding-context

> a performant react context

Latest version **1.0.0** (published 2021-12-07) · MIT license · 0 weekly downloads

## Install

```sh
npm install react-binding-context
pnpm add react-binding-context
yarn add react-binding-context
bun add react-binding-context
```

## Health

**Score 15/100 (F)** — status: abandoned.

Positive: no vulnerabilities.

Warnings: low downloads; no types; no esm support.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 1.0.0 |
| Published | 2021-12-07 |
| First published | 2021-11-28 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | none |
| Module format | CommonJS |
| Node | >=9 |
| Dependencies | 2 |
| Unpacked size | 25.2 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 165 |
| Author | guiyep |
| Maintainers | guiyep |
| Keywords | react, context, performance, hooks, bind, state, data |

## Links

- npm: https://www.npmjs.com/package/react-binding-context
- Repository: https://github.com/guiyep/react-select-virtualized
- npm.io page: https://npm.io/package/react-binding-context

## Dependencies (2)

- [lodash.get](https://npm.io/package/lodash.get.md) ^4.4.2
- [lodash.debounce](https://npm.io/package/lodash.debounce.md) ^4.0.8

## Alternatives

- [mobx-react](https://npm.io/package/mobx-react.md) — 2.8M weekly downloads
- [rc-tree](https://npm.io/package/rc-tree.md) — 2.6M weekly downloads
- [@react-oauth/google](https://npm.io/package/@react-oauth/google.md) — 1.3M weekly downloads
- [@wagmi/connectors](https://npm.io/package/@wagmi/connectors.md) — 877.0K weekly downloads
- [vee-validate](https://npm.io/package/vee-validate.md) — 836.4K weekly downloads

## Recent versions

- 1.0.0 (latest) — 2021-12-07
- 0.1.0 — 2021-11-28

## README

# react-lightning-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` and it is only **12kb**!!!!

## Why ?

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.

## Libraries comparison

The bordered area is where the element is re-rendered. In the examples, the button is updating only one of the properties in the internal Context value.

| Using `react-lightning-context`  | Using `React Context`                  |
| -------------------------------- | -------------------------------------- |
| ![with gif](/assets/with-op.gif) | ![without gif](/assets/without-op.gif) |

## How to install

```terminal
  yarn add react-lightning-context
```

## How to use it without Hooks

The main idea is following the same patterns and api that `React Context` provides with a little twist.

```jsx
  const defaultValue = { valueA: { a: { b: 222, r: 333 } }, valueB: 222, valueC: 444 };
  const Context = createLightningContext(defaultValue);

  // `listenTo` can be (some examples):
  // - valueA -> { a: { b: 222, r: 333 } }
  // - valueA.a -> { b: 222, r: 333 }
  // - valueA.a.b -> 222

  const ExampleA = () => (
    <Context.Provider>
      <Context.Consumer listenTo={['valueC']}>
        {({ valueC }) => <label>{valueC}</label> }
      </Context.Consumer>
    </Context.Provider>);
};
```

### What is going on here?

- `createLightningContext` is creating the context.
- `Context.Provider` is defining the area in which the context data is going to be shared.
- `Context.Consumer` will listen to changes in the Context value and will re-rendered **ONLY** when the values on the `listenTo` prop in the context has changed. You can listen to more than one field, or you can go deep down into the props. ex: `valueA.a.r`.

## How to use it with Hooks

The main idea ia following the same patterns and api that `React Context` provides with a little twist. This is doing the same as the previous example but with hooks.

```jsx
  const defaultValue = { valueA: { a: { b: 222, r: 333 } }, valueB: 222, valueC: 444 };
  const Context = createLightningContext(defaultValue);

  const UseLightningContextHookComponent = () => {
    const { valueC } = useLightningContext({ listenTo: ['valueC'] }, Context);
    return <label>{valueC}</label>;
  };

  // `listenTo` can be (some examples):
  // - valueA -> { a: { b: 222, r: 333 } }
  // - valueA.a -> { b: 222, r: 333 }
  // - valueA.a.b -> 222

  const ExampleA = () => (
    <Context.Provider>
      <UseLightningContextHookComponent />
    </Context.Provider>);
};
```

### What is going on here?

- `createLightningContext` is creating the context.
- `Context.Provider` is defining the area in which the context data is going to be shared.
- `useLightningContext` will listen to changes in the Context value and will be updated **ONLY** when the values on the `listenTo` prop in the context has changed. You can listen to more than one field, or you can go deep down into the props. ex: `valueA.a.r`.

## API Documentation

| Name                                                          | Supported ? | Description                                                                                  |
| ------------------------------------------------------------- | ----------- | -------------------------------------------------------------------------------------------- |
| `React.createContext` **renamed to** `createLightningContext` | **Yes**     | It is how we create the context we use createLightningContext 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` **renamed to** `useLightningContext`             | **Yes**     | A way of consuming a context value using hook. Similar to useContext                         |
| `Context.Mutator`                                             | **New**     | A component that provides a way of mutating the value of the context                         |
| `useLightningContextMutator`                                  | **New**     | A Hook that provides a way of mutating the value of the context                              |

### createLightningContext

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 with what `concurrentMode` will have. |

It **returns** the `Provider, Consumer, Mutator` components

#### Example

```js
const Context = createLightningContext({ value: 'test' });

const Context = createLightningContext({ value: 'test' }, { waitBeforeUpdate: true });
```

### Context.Provider

This does not have any props. Same as `React.Context` it wraps the context experience.

#### Example

```jsx
const Context = createLightningContext({ value: 'test' });

const TopLevelExperience = () => {
  return <Context.Provider>// ... 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                                                                      |
| ---------- | --------------- | -------- | -------------------------------------------------------------------------------- |
| `listenTo` | 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

#### Example

```jsx
const Context = createLightningContext({ value: { first: 1, second: 2 } });

const TopLevelExperience = () => {
  return <Context.Provider>
    <Context.Consumer listenTo={['value.first', 'value.seconds']}>
    {
      (values) => //... anything to render
    }
    </Context.Consumer>
  </Context.Provider>;
};
```

#### Return value example

if **listenTo** is `['value.first', 'value.seconds']` the render function that will execute is

```js
  ({ 'value.first': 123, 'value.seconds': 333 }) => //...anything to render
```

### useLightningContext

Same as `Consumer` but as a Hook api (similar to the `useContext` hook)

| Properties | Type                                     | Required | Description                                                                      |
| ---------- | ---------------------------------------- | -------- | -------------------------------------------------------------------------------- |
| `listenTo` | Array<String>                            | **Yes**  | Properties from the `Context.value` that you want to listen to. It can be nested |
| `Context`  | `createLightningContext` returned object | **Yes**  | The context you are using                                                        |

```js
const result = useLightningContext({ listenTo: [...] }, 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 updated context value

```js
setContextValue((value) => {
  return {
    ...value,
    ...yourChangeGoesHere,
  };
});
```

#### Example

```jsx
const Context = createLightningContext({ value: { first: 1, second: 2 } });

const TopLevelExperience = () => {
  return <Context.Provider>
    <Context.Mutator>
      {
        ({ setContextValue }) => //... anything that want to use setContextValue
      }
    </Context.Mutator>
  </Context.Provider>;
};
```

### useLightningContextMutator

Same as `Context.Mutator` but as a Hook.

| Properties | Type                                     | Required | Description               |
| ---------- | ---------------------------------------- | -------- | ------------------------- |
| `Context`  | `createLightningContext` returned object | **Yes**  | The context you are using |

#### Example

```jsx
const setContextValue = useLightningContextMutator(Context);
```

---
_Source: https://npm.io/package/react-binding-context · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
