• Stars
    star
    546
  • Rank 81,396 (Top 2 %)
  • Language
    JavaScript
  • License
    MIT License
  • Created over 5 years ago
  • Updated about 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Test tearing and branching in React concurrent rendering

Will this React global state work in concurrent rendering?

Test tearing and branching in React concurrent rendering

Introduction

React 18 comes with a new feature called "concurrent rendering". With global state, there's a theoretical issue called "tearing" that might occur in React concurrent rendering.

Let's test the behavior!

What is tearing?

What is branching?

How does it work?

A small app is implemented with each library. The state has one count. The app shows the count in fifty components.

There's a button outside of React and if it's clicked it will trigger state mutation. This is to emulate mutating an external state outside of React, for example updating state by Redux middleware.

The render has intentionally expensive computation. If the mutation happens during rendering with in a tree, there could be an inconsistency in the state. If it finds the inconsistency, the test will fail.

How to run

git clone https://github.com/dai-shi/will-this-react-global-state-work-in-concurrent-rendering.git
cd will-this-react-global-state-work-in-concurrent-rendering
yarn install
yarn run build-all
yarn run jest

To automatically run tests and update the README.md on OSX:

yarn jest:json
yarn jest:update

Screencast (old one with react-redux v7. v8 works great.)

Preview

Test scenario

  • With useTransition
    • Level 1
      • 1: No tearing finally on update
      • 2: No tearing finally on mount
    • Level 2
      • 3: No tearing temporarily on update
      • 4: No tearing temporarily on mount
    • Level 3
      • 5: Can interrupt render (time slicing)
      • 6: Can branch state (wip state)
  • With useDeferredValue
    • Level 1
      • 7: No tearing finally on update
      • 8: No tearing finally on mount
    • Level 2
      • 9: No tearing temporarily on update
      • 10: No tearing temporarily on mount

Results

Raw Output
   With useTransition
     Level 1
       ✓ No tearing finally on update (7990 ms)
       ✓ No tearing finally on mount (4608 ms)
     Level 2
       ✓ No tearing temporarily on update (12955 ms)
       ✓ No tearing temporarily on mount (4546 ms)
     Level 3
       ✕ Can interrupt render (time slicing) (7926 ms)
       ✕ Can branch state (wip state) (6655 ms)
   With useDeferredValue
     Level 1
       ✓ No tearing finally on update (9568 ms)
       ✓ No tearing finally on mount (4544 ms)
     Level 2
       ✓ No tearing temporarily on update (14627 ms)
       ✓ No tearing temporarily on mount (4569 ms)
 zustand
   With useTransition
     Level 1
       ✓ No tearing finally on update (7994 ms)
       ✓ No tearing finally on mount (4623 ms)
     Level 2
       ✓ No tearing temporarily on update (12966 ms)
       ✓ No tearing temporarily on mount (4505 ms)
     Level 3
       ✕ Can interrupt render (time slicing) (7922 ms)
       ✕ Can branch state (wip state) (6679 ms)
   With useDeferredValue
     Level 1
       ✓ No tearing finally on update (9631 ms)
       ✓ No tearing finally on mount (4641 ms)
     Level 2
       ✓ No tearing temporarily on update (14656 ms)
       ✓ No tearing temporarily on mount (4544 ms)
 react-tracked
   With useTransition
     Level 1
       ✓ No tearing finally on update (5586 ms)
       ✓ No tearing finally on mount (9520 ms)
     Level 2
       ✓ No tearing temporarily on update (8625 ms)
       ✓ No tearing temporarily on mount (9455 ms)
     Level 3
       ✓ Can interrupt render (time slicing) (3555 ms)
       ✓ Can branch state (wip state) (8216 ms)
   With useDeferredValue
     Level 1
       ✓ No tearing finally on update (15399 ms)
       ✓ No tearing finally on mount (6528 ms)
     Level 2
       ✓ No tearing temporarily on update (19473 ms)
       ✓ No tearing temporarily on mount (8479 ms)
 constate
   With useTransition
     Level 1
       ✓ No tearing finally on update (4526 ms)
       ✓ No tearing finally on mount (7464 ms)
     Level 2
       ✓ No tearing temporarily on update (8619 ms)
       ✓ No tearing temporarily on mount (8491 ms)
     Level 3
       ✓ Can interrupt render (time slicing) (3635 ms)
       ✓ Can branch state (wip state) (5159 ms)
   With useDeferredValue
     Level 1
       ✓ No tearing finally on update (9626 ms)
       ✓ No tearing finally on mount (6629 ms)
     Level 2
       ✓ No tearing temporarily on update (14643 ms)
       ✓ No tearing temporarily on mount (5578 ms)
 react-hooks-global-state
   With useTransition
     Level 1
       ✓ No tearing finally on update (7954 ms)
       ✓ No tearing finally on mount (4564 ms)
     Level 2
       ✓ No tearing temporarily on update (12975 ms)
       ✓ No tearing temporarily on mount (4525 ms)
     Level 3
       ✕ Can interrupt render (time slicing) (7896 ms)
       ✕ Can branch state (wip state) (6648 ms)
   With useDeferredValue
     Level 1
       ✓ No tearing finally on update (9624 ms)
       ✓ No tearing finally on mount (4547 ms)
     Level 2
       ✓ No tearing temporarily on update (14636 ms)
       ✓ No tearing temporarily on mount (4549 ms)
 use-context-selector-base
   With useTransition
     Level 1
       ✓ No tearing finally on update (7851 ms)
       ✓ No tearing finally on mount (8476 ms)
     Level 2
       ✓ No tearing temporarily on update (12836 ms)
       ✓ No tearing temporarily on mount (8496 ms)
     Level 3
       ✕ Can interrupt render (time slicing) (7846 ms)
       ✕ Can branch state (wip state) (7629 ms)
   With useDeferredValue
     Level 1
       ✓ No tearing finally on update (9706 ms)
       ✓ No tearing finally on mount (5650 ms)
     Level 2
       ✓ No tearing temporarily on update (14623 ms)
       ✓ No tearing temporarily on mount (5590 ms)
 use-context-selector
   With useTransition
     Level 1
       ✓ No tearing finally on update (5503 ms)
       ✓ No tearing finally on mount (11504 ms)
     Level 2
       ✓ No tearing temporarily on update (8629 ms)
       ✓ No tearing temporarily on mount (11478 ms)
     Level 3
       ✓ Can interrupt render (time slicing) (3565 ms)
       ✓ Can branch state (wip state) (8202 ms)
   With useDeferredValue
     Level 1
       ✓ No tearing finally on update (15341 ms)
       ✓ No tearing finally on mount (6542 ms)
     Level 2
       ✓ No tearing temporarily on update (20063 ms)
       ✓ No tearing temporarily on mount (8598 ms)
 use-subscription
   With useTransition
     Level 1
       ✓ No tearing finally on update (7989 ms)
       ✓ No tearing finally on mount (4610 ms)
     Level 2
       ✓ No tearing temporarily on update (12955 ms)
       ✓ No tearing temporarily on mount (4541 ms)
     Level 3
       ✕ Can interrupt render (time slicing) (7947 ms)
       ✕ Can branch state (wip state) (6656 ms)
   With useDeferredValue
     Level 1
       ✓ No tearing finally on update (9612 ms)
       ✓ No tearing finally on mount (4555 ms)
     Level 2
       ✓ No tearing temporarily on update (14580 ms)
       ✓ No tearing temporarily on mount (4588 ms)
 apollo-client
   With useTransition
     Level 1
       ✓ No tearing finally on update (8142 ms)
       ✓ No tearing finally on mount (4638 ms)
     Level 2
       ✓ No tearing temporarily on update (13105 ms)
       ✓ No tearing temporarily on mount (5551 ms)
     Level 3
       ✕ Can interrupt render (time slicing) (8083 ms)
       ✕ Can branch state (wip state) (7756 ms)
   With useDeferredValue
     Level 1
       ✓ No tearing finally on update (6514 ms)
       ✓ No tearing finally on mount (5679 ms)
     Level 2
       ✓ No tearing temporarily on update (9692 ms)
       ✓ No tearing temporarily on mount (4724 ms)
 recoil
   With useTransition
     Level 1
       ✓ No tearing finally on update (8119 ms)
       ✓ No tearing finally on mount (4729 ms)
     Level 2
       ✓ No tearing temporarily on update (13109 ms)
       ✓ No tearing temporarily on mount (4670 ms)
     Level 3
       ✕ Can interrupt render (time slicing) (8047 ms)
       ✕ Can branch state (wip state) (6808 ms)
   With useDeferredValue
     Level 1
       ✓ No tearing finally on update (9780 ms)
       ✓ No tearing finally on mount (4673 ms)
     Level 2
       ✓ No tearing temporarily on update (14784 ms)
       ✓ No tearing temporarily on mount (4667 ms)
 recoil_UNSTABLE
   With useTransition
     Level 1
       ✓ No tearing finally on update (5736 ms)
       ✓ No tearing finally on mount (5624 ms)
     Level 2
       ✓ No tearing temporarily on update (8723 ms)
       ✕ No tearing temporarily on mount (5586 ms)
     Level 3
       ✓ Can interrupt render (time slicing) (3763 ms)
       ✕ Can branch state (wip state) (10277 ms)
   With useDeferredValue
     Level 1
       ✓ No tearing finally on update (11399 ms)
       ✓ No tearing finally on mount (5612 ms)
     Level 2
       ✓ No tearing temporarily on update (15529 ms)
       ✕ No tearing temporarily on mount (5579 ms)
 jotai
   With useTransition
     Level 1
       ✓ No tearing finally on update (5633 ms)
       ✓ No tearing finally on mount (6580 ms)
     Level 2
       ✓ No tearing temporarily on update (9753 ms)
       ✕ No tearing temporarily on mount (6550 ms)
     Level 3
       ✓ Can interrupt render (time slicing) (4707 ms)
       ✕ Can branch state (wip state) (10238 ms)
   With useDeferredValue
     Level 1
       ✓ No tearing finally on update (10713 ms)
       ✓ No tearing finally on mount (6736 ms)
     Level 2
       ✓ No tearing temporarily on update (15726 ms)
       ✕ No tearing temporarily on mount (5661 ms)
 use-atom
   With useTransition
     Level 1
       ✓ No tearing finally on update (6616 ms)
       ✓ No tearing finally on mount (9592 ms)
     Level 2
       ✓ No tearing temporarily on update (9713 ms)
       ✓ No tearing temporarily on mount (9559 ms)
     Level 3
       ✓ Can interrupt render (time slicing) (4749 ms)
       ✓ Can branch state (wip state) (9292 ms)
   With useDeferredValue
     Level 1
       ✓ No tearing finally on update (16565 ms)
       ✓ No tearing finally on mount (6647 ms)
     Level 2
       ✓ No tearing temporarily on update (20596 ms)
       ✓ No tearing temporarily on mount (6604 ms)
 valtio
   With useTransition
     Level 1
       ✓ No tearing finally on update (8087 ms)
       ✓ No tearing finally on mount (4701 ms)
     Level 2
       ✓ No tearing temporarily on update (13031 ms)
       ✓ No tearing temporarily on mount (4741 ms)
     Level 3
       ✕ Can interrupt render (time slicing) (8028 ms)
       ✕ Can branch state (wip state) (6785 ms)
   With useDeferredValue
     Level 1
       ✓ No tearing finally on update (9729 ms)
       ✓ No tearing finally on mount (4694 ms)
     Level 2
       ✓ No tearing temporarily on update (14789 ms)
       ✓ No tearing temporarily on mount (4682 ms)
 effector
   With useTransition
     Level 1
       ✓ No tearing finally on update (8153 ms)
       ✓ No tearing finally on mount (4653 ms)
     Level 2
       ✓ No tearing temporarily on update (13080 ms)
       ✓ No tearing temporarily on mount (4668 ms)
     Level 3
       ✕ Can interrupt render (time slicing) (8003 ms)
       ✕ Can branch state (wip state) (6776 ms)
   With useDeferredValue
     Level 1
       ✓ No tearing finally on update (9689 ms)
       ✓ No tearing finally on mount (4730 ms)
     Level 2
       ✓ No tearing temporarily on update (14725 ms)
       ✓ No tearing temporarily on mount (4608 ms)
 react-rxjs
   With useTransition
     Level 1
       ✓ No tearing finally on update (8066 ms)
       ✓ No tearing finally on mount (4658 ms)
     Level 2
       ✓ No tearing temporarily on update (13040 ms)
       ✓ No tearing temporarily on mount (4637 ms)
     Level 3
       ✕ Can interrupt render (time slicing) (8027 ms)
       ✕ Can branch state (wip state) (6797 ms)
   With useDeferredValue
     Level 1
       ✓ No tearing finally on update (9765 ms)
       ✓ No tearing finally on mount (4625 ms)
     Level 2
       ✓ No tearing temporarily on update (14783 ms)
       ✓ No tearing temporarily on mount (4642 ms)
 simplux
   With useTransition
     Level 1
       ✓ No tearing finally on update (4613 ms)
       ✓ No tearing finally on mount (8591 ms)
     Level 2
       ✓ No tearing temporarily on update (8730 ms)
       ✓ No tearing temporarily on mount (8572 ms)
     Level 3
       ✓ Can interrupt render (time slicing) (3712 ms)
       ✕ Can branch state (wip state) (9293 ms)
   With useDeferredValue
     Level 1
       ✓ No tearing finally on update (9718 ms)
       ✓ No tearing finally on mount (6708 ms)
     Level 2
       ✓ No tearing temporarily on update (14698 ms)
       ✓ No tearing temporarily on mount (5680 ms)
 react-query
   With useTransition
     Level 1
       ✓ No tearing finally on update (8131 ms)
       ✓ No tearing finally on mount (4716 ms)
     Level 2
       ✕ No tearing temporarily on update (13174 ms)
       ✓ No tearing temporarily on mount (4655 ms)
     Level 3
       ✕ Can interrupt render (time slicing) (8120 ms)
       ✕ Can branch state (wip state) (6807 ms)
   With useDeferredValue
     Level 1
       ✓ No tearing finally on update (9594 ms)
       ✓ No tearing finally on mount (4665 ms)
     Level 2
       ✓ No tearing temporarily on update (13721 ms)
       ✓ No tearing temporarily on mount (4653 ms)
 mobx-react-lite
   With useTransition
     Level 1
       ✓ No tearing finally on update (4651 ms)
       ✓ No tearing finally on mount (5610 ms)
     Level 2
       ✕ No tearing temporarily on update (8739 ms)
       ✕ No tearing temporarily on mount (6586 ms)
     Level 3
       ✓ Can interrupt render (time slicing) (3692 ms)
       ✕ Can branch state (wip state) (3071 ms)
   With useDeferredValue
     Level 1
       ✓ No tearing finally on update (9777 ms)
       ✓ No tearing finally on mount (6595 ms)
     Level 2
       ✓ No tearing temporarily on update (14724 ms)
       ✕ No tearing temporarily on mount (6568 ms)

Test12345678910
react-redux
zustand
react-tracked
constate
react-hooks-global-state
use-context-selector (w/ useReducer, w/o useContextUpdate)
use-context-selector (w/ useReducer)
use-subscription (w/ redux)
apollo-client
recoil
recoil (UNSTABLE)
jotai
use-atom
valtio
effector
react-rxjs
simplux
react-query
mobx-react-lite

Caveats

  • Tearing and state branching may not be an issue depending on app requirements.
  • The test is done in a very limited way.
    • Passing tests don't guarantee anything.
  • The results may not be accurate.
    • Do not fully trust the results.

If you are interested

The reason why I created this is to test my projects.

Contributing

This repository is a tool for us to test some of global state libraries. While it is totally fine to use the tool for other libraries under the license, we don't generally accept adding a new library to the repository.

However, we are interested in various approaches. If you have any suggestions feel free to open issues or pull requests. We may consider adding (and removing) libraries. Questions and discussions are also welcome in issues.

For listing global state libraries, we have another repository https://github.com/dai-shi/lets-compare-global-state-with-react-hooks in which we accept contributions. It's recommended to run this tool and we put the result there, possibly a reference link to a PR in this repository or a fork of this repository.

More Repositories

1

waku

⛩️ The minimal React framework
TypeScript
4,363
star
2

react-tracked

State usage tracking with Proxies. Optimize re-renders for useState/useReducer, React Redux, Zustand and others.
TypeScript
2,663
star
3

use-context-selector

React useContextSelector hook in userland
TypeScript
2,518
star
4

excalidraw-animate

A tool to animate Excalidraw drawings
TypeScript
1,252
star
5

react-hooks-global-state

[NOT MAINTAINED] Simple global state for React with Hooks API without Context API
TypeScript
1,099
star
6

proxy-memoize

Intuitive magical memoization library with Proxy and WeakMap
TypeScript
715
star
7

react-hooks-worker

React custom hooks for web workers
TypeScript
698
star
8

reactive-react-redux

[NOT MAINTAINED] React Redux binding with React Hooks and Proxy
TypeScript
502
star
9

react-hooks-async

[NOT MAINTAINED] React custom hooks for async functions with abortability and composability
JavaScript
496
star
10

excalidraw-claymate

A tool based on Excalidraw to create stop motion animations and slides.
TypeScript
482
star
11

react-hooks-fetch

[NOT MAINTAINED] Minimal data fetching library with React Suspense
TypeScript
397
star
12

react-worker-components

React Worker Components simplify using Web Workers
TypeScript
337
star
13

use-signals

An experimental React hook for TC39 signals
TypeScript
309
star
14

react-suspense-fetch

[NOT MAINTAINED] A low-level library for React Suspense for Data Fetching
TypeScript
297
star
15

katachidraw

SVG based drawing tool and react-native component
TypeScript
290
star
16

proxy-compare

Compare two objects using accessed properties with Proxy
TypeScript
268
star
17

redux-in-worker

Entire Redux in Web Worker
TypeScript
258
star
18

social-cms-backend

Express middleware to provide schema-less REST APIs for creating a social networking website primarily using angular.js. It comes with built-in authentication, authorization and notification features.
JavaScript
216
star
19

use-reducer-async

React useReducer with async actions
TypeScript
178
star
20

valtio-yjs

valtio-yjs makes yjs state easy
TypeScript
177
star
21

connect-prerenderer

Express/connect middleware to pre-render ajax page for non-ajax browsers, especially using angular.js
JavaScript
161
star
22

typescript-expo-apollo-boilerplate

[NOT MAINTAINED] Clean boilerplate for TypeScript + Expo (React Native) + React Apollo (GraphQL)
TypeScript
144
star
23

es-beautifier

[NOT MAINTAINED] ECMAScript beautifier based on eslint
JavaScript
120
star
24

create-react-signals

A factory function to create signals for React
TypeScript
111
star
25

zustand-signal

Another React binding for Zustand
TypeScript
109
star
26

react18-use

React 19 use hook shim
TypeScript
109
star
27

use-atom

Yet another implementation for Jotai atoms without side effects
TypeScript
108
star
28

remote-faces

A tool for Working From Home: Share your webcam images with your colleagues
JavaScript
95
star
29

react-suspense-router

[NOT MAINTAINED] React Router for React Suspense and Render-as-You-Fetch
TypeScript
87
star
30

continuation.js

A module for tail call optimization by Continuation Passing Style (CPS) transformation with trampoline technique for Node.js
JavaScript
78
star
31

rss-pipes

RSS feed aggregator by Node.js
JavaScript
74
star
32

derive-zustand

A function to create a derived Zustand store from stores
TypeScript
71
star
33

lets-compare-global-state-with-react-hooks

Comparing global state libraries with React Hooks
59
star
34

use-zustand

Another custom hook to use Zustand vanilla store
TypeScript
57
star
35

easy-livereload

Express middleware to use livereload2 easily (both server and client)
JavaScript
56
star
36

codeonmobile

A coding tool on mobile devices targeting GitHub/Codeship/Heroku
JavaScript
55
star
37

valtio-signal

Another React binding for Valtio proxy state
TypeScript
50
star
38

connect-cache-manifest

Express/connect middleware to generate HTML5 cache manifest file.
JavaScript
49
star
39

excalidraw-gallery

A tool to display Excalidraw drawings
JavaScript
37
star
40

excalidraw-layers

A tool to view layers of Excalidraw drawings
TypeScript
33
star
41

notes-app-sample

A sample HTML5 web app using social-cms-backend (the BMEAN stack)
JavaScript
33
star
42

express-react-redux

Express middleware for React/Redux applications
JavaScript
30
star
43

svelte3-redux

[NOT MAINTAINED] Redux for Svelte 3
TypeScript
30
star
44

react-suspense-worker

[NOT MAINTAINED] React Suspense for Web Worker with Comlink
TypeScript
26
star
45

react-native-dom-expo

[NOT MAINTAINED] A patch library to make Expo work with react-native-dom
JavaScript
25
star
46

react-context-global-state

[NOT MAINTAINED] Simple global state for React with Context API
JavaScript
23
star
47

gqless-hook

[NOT MAINTAINED] Yet another React hook for gqless
TypeScript
22
star
48

use-valtio

Another custom hook to use Valtio proxy state
TypeScript
21
star
49

react-hooks-render-props

[NOT MAINTAINED] A hacking custom hook to emulate render props
JavaScript
18
star
50

benchmark-octane

Octane benchmark for Node.js
JavaScript
18
star
51

recoildux

[NOT MAINTAINED] Recoil inspired implementation with Redux
TypeScript
16
star
52

react-compose-state

A helper function to attach state to stateless function components
JavaScript
16
star
53

gunosy-rss

[OBSOLETE] Gunosy RSS feed web service by Node.js
JavaScript
15
star
54

apollo-link-lazy

Apollo Link for lazy loading
JavaScript
14
star
55

react-suspense-router-demo

[NOT MAINTAINED] A demo app with react-suspense-router
TypeScript
11
star
56

react-apollo-github-api-infinite-scroll-example

React Apollo GitHub GraphQL API infinite scroll example code
JavaScript
11
star
57

twitter-clone-sample

JavaScript
7
star
58

blog

Personal blog
Less
6
star
59

waku-vercel-starter

TypeScript
5
star
60

meteor-fan

HTML
4
star
61

waku-netlify-starter

TypeScript
4
star
62

dai-shi

3
star
63

minimal-apollo-example

Minimal Apollo stack example code
JavaScript
2
star
64

react-compose-onmount

A helper function to attach onmount handler to stateless function components
JavaScript
2
star
65

GBrain

A Google AppEngine web app for sharing brains.
Java
1
star
66

meteor-google-maps-example

JavaScript
1
star
67

meteor-blaze-google-maps

Easy Blaze template for Google Maps with reactivity
JavaScript
1
star
68

meteor-blaze-showhide

Handy block helpers for show/hide functionality in Blaze
JavaScript
1
star
69

meteor-facebook-server-api

A Meteor package to provide Facebook Graph API
JavaScript
1
star