Awesome
Let's compare global state with React Hooks
Comparing global state libraries with React Hooks
Motivation
I have been developing several libraries for global state with React Hooks. While developing them, I was interested in comparing with existing libraries. It turns out there are various points to compare, showing characteristics of such libraries.
I started creating a comparison table in the issue. As the table becomes bigger, let's create a separate repo so that library authors can contribute improving the comparison.
Comparison points
- Does it use React Context? What is context value?
- Does it use subscription for state propagation?
- Does it have render optimization? What is the technique?
- Does it have dependencies? What are they?
- What's the level of compatibility with concurrent rendering?
- Bundle size (Minified + Gzipped)
Notes
Render optimization means avoiding unnecessary re-renders.
If a state object is { a: 1, b: 2 }
and a component only uses a
,
it won't re-render if only b
is changed.
For "tearing" and "state branching", refer https://github.com/dai-shi/will-this-react-global-state-work-in-concurrent-mode. These are not necessarily problems depending on requirements.
Comparison Table
<table> <tr> <th></th> <th>1</th> <th>2</th> <th>3</th> <th>4</th> <th>5</th> <th>6</th> </tr> <tr> <th><a href="https://github.com/dai-shi/react-tracked">react-tracked</a></th> <td>State-based object</td> <td>Yes</td> <td>Proxy-based tracking and selector function</td> <td>use-context-selector, proxy-compare</td> <td>Level 3</td> <td><a href="https://bundlephobia.com/package/react-tracked@1.7.5">1.9kB</a></td> </tr> <tr> <th><a href="https://github.com/diegohaz/constate">constate</a></th> <td>State-based object</td> <td>No</td> <td>Multiple contexts</td> <td>No</td> <td>Level 3</td> <td><a href="https://bundlephobia.com/package/constate@3.3.0">508B<a/></td> </tr> <tr> <th><a href="https://github.com/jamiebuilds/unstated-next">unstated-next</a></th> <td>State-based object</td> <td>No</td> <td>No</td> <td>No</td> <td>Unknown</td> <td><a href="https://bundlephobia.com/package/unstated-next@1.1.0">362B</a></td> </tr> <tr> <th><a href="https://github.com/pmndrs/zustand">zustand</a></th> <td>No</td> <td>Yes</td> <td>Selector function</td> <td>No</td> <td>Level 2</td> <td><a href="https://bundlephobia.com/package/zustand@3.6.8">954B</a></td> </tr> <tr> <th><a href="https://github.com/atlassian/react-sweet-state">react-sweet-state</a></th> <td>State-based object</td> <td>Yes</td> <td>Selector function</td> <td>No</td> <td>Unknown</td> <td><a href="https://bundlephobia.com/package/react-sweet-state@2.5.2">3.6kB</a></td> </tr> <tr> <th><a href="https://github.com/storeon/storeon">storeon</a></th> <td>Store</td> <td>Yes</td> <td>Shallow state properties</td> <td>No</td> <td>Unknown</td> <td><a href="https://bundlephobia.com/package/storeon@3.1.4">370B</a></td> </tr> <tr> <th><a href="https://github.com/dai-shi/react-hooks-global-state">react-hooks-global-state</a></th> <td>No</td> <td>Yes</td> <td>Shallow state properties</td> <td>No</td> <td>Level 1</td> <td><a href="https://bundlephobia.com/package/react-hooks-global-state@1.0.2">1.1kB</a></td> </tr> <tr> <th><a href="https://github.com/reduxjs/react-redux">react-redux (hooks)</a></th> <td>Store</td> <td>Yes</td> <td>Selector function</td> <td>Redux</td> <td>Level 2</td> <td><a href="https://bundlephobia.com/package/react-redux@7.2.6">5.4kB</a></td> </tr> <tr> <th><a href="https://github.com/ctrlplusb/easy-peasy">easy-peasy</a></th> <td>Store</td> <td>Yes</td> <td>Selector function</td> <td>Redux, immer and so on</td> <td>Unknown</td> <td><a href="https://bundlephobia.com/package/easy-peasy@5.0.4">9.6kB</a></td> </tr> <tr> <th><a href="https://github.com/mobxjs/mobx-react-lite">mobx-react-lite</a></th> <td>Mutable state object</td> <td>No</td> <td>Proxy-based tracking</td> <td>MobX</td> <td>Unknown</td> <td><a href="https://bundlephobia.com/package/mobx-react-lite@3.2.2">2kB</a></td> </tr> <tr> <th><a href="https://github.com/avkonst/hookstate">hookstate</a></th> <td>No</td> <td>Yes</td> <td>Proxy-based tracking</td> <td>No</td> <td>Unknown</td> <td><a href="https://bundlephobia.com/package/@hookstate/core@3.0.13">4.5kB</a></td> </tr> <tr> <th><a href="https://github.com/facebookexperimental/Recoil">recoil</a></th> <td>Probably rich state-based object</td> <td>Yes with atom abstraction</td> <td>atoms (incl. selectors)</td> <td>No</td> <td>Level 2</td> <td><a href="https://bundlephobia.com/package/recoil@0.5.2">21.1kB</a></td> </tr> <tr> <th><a href="https://github.com/RisingStack/react-easy-state">react-easy-state</a>(Note: This library does not provide Hooks API)</th> <td>No</td> <td>Yes with observer</td> <td>observer</td> <td>@nx-js/observer-util</td> <td>Unknown</td> <td><a href="https://bundlephobia.com/package/react-easy-state@6.1.3">2.9kB</a></td> </tr> <tr> <th><a href="https://github.com/oleggrishechkin/react-tagged-state">react-tagged-state</a></th> <td>No</td> <td>Yes</td> <td>Selector function with deps tracking</td> <td>No</td> <td>Unknown</td> <td><a href="https://bundlephobia.com/package/react-tagged-state@1.0.6">804B</a></td> </tr> <tr> <th><a href="https://github.com/agile-ts/agile">agile-ts</a></th> <td>No</td> <td>Yes</td> <td>Runtime combining multiple rerender triggers</td> <td>No</td> <td>Unknown</td> <td><a href="https://bundlephobia.com/package/@agile-ts/core@0.2.7">12.7kB<a></td> </tr> <tr> <th><a href="https://github.com/pmndrs/jotai">jotai</a></th> <td>Store</td> <td>Yes, atom-based subscription</td> <td>atoms</td> <td>No</td> <td>Level 1 / (Level 3)</td> <td><a href="https://bundlephobia.com/package/jotai@1.4.9">2.6kB</a></td> </tr> <tr> <th><a href="https://github.com/pmndrs/valtio">valtio</a></th> <td>No</td> <td>Yes</td> <td>Proxy-based tracking</td> <td>proxy-compare</td> <td>Level 2</td> <td><a href="https://bundlephobia.com/package/valtio@1.2.7">2.5kB</a></td> </tr> </table>Contribution
If you have questions, suggestions or corrections, please file an issue.
If you have a new library to add, please file a pull request. Please add a new row at the end of the table.