JSPM

  • Created
  • Published
  • Downloads 203937
  • Score
    100M100P100Q172287F
  • License MIT

React shared state with performance

Package Exports

  • react-tracked

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (react-tracked) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

react-tracked

Build Status npm version bundle size

Super fast React global/shared state with context and hooks

Motivation

I have been developing reactive-react-redux which is an alternative to react-redux providing state usage tracking for optimization. This library provides almost same functionality, but without Redux. No middleware, no devtools, and/but no dependencies.

Analogies

  • Like constate and unstated-next, this receives useValue hook. Unlike them, this doesn't use factory pattern.
  • Like react-redux and zustand, it's optimized to trigger re-render only necessarily. Unlike them, this tracks state usage with Proxy for optomization, so you don't need a "selector".

Some other notes:

  • not only useReducer but also useState can be used for useValue
  • useSelector emulates that in react-redux

Install

npm install react-tracked

Usage

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

import {
  TrackedProvider,
  useTracked,
} from 'react-tracked';

const initialState = {
  counter: 0,
  text: 'hello',
};

const reducer = (state, action) => {
  switch (action.type) {
    case 'increment': return { ...state, counter: state.counter + 1 };
    case 'decrement': return { ...state, counter: state.counter - 1 };
    case 'setText': return { ...state, text: action.text };
    default: throw new Error(`unknown action type: ${action.type}`);
  }
};

const useValue = () => useReducer(reducer, initialState);

const Counter = () => {
  const [state, dispatch] = useTracked();
  return (
    <div>
      {Math.random()}
      <div>
        <span>Count:{state.counter}</span>
        <button type="button" onClick={() => dispatch({ type: 'increment' })}>+1</button>
        <button type="button" onClick={() => dispatch({ type: 'decrement' })}>-1</button>
      </div>
    </div>
  );
};

const TextBox = () => {
  const [state, dispatch] = useTracked();
  return (
    <div>
      {Math.random()}
      <div>
        <span>Text:{state.text}</span>
        <input value={state.text} onChange={event => dispatch({ type: 'setText', text: event.target.value })} />
      </div>
    </div>
  );
};

const App = () => (
  <TrackedProvider useValue={useValue}>
    <h1>Counter</h1>
    <Counter />
    <Counter />
    <h1>TextBox</h1>
    <TextBox />
    <TextBox />
  </TrackedProvider>
);

ReactDOM.render(<App />, document.getElementById('app'));

Examples

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

PORT=8080 npm run examples:minimal

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

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