Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

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

License

NotificationsYou must be signed in to change notification settings

sukvvon/react-tracked

 
 

Repository files navigation

logo

React Tracked

CInpmsizediscord

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

Documentation site:https://react-tracked.js.org

Introduction

Preventing re-renders is one of performance issues in React.Smaller apps wouldn't usually suffer from such a performance issue,but once apps have a central global state that would be used inmany components. The performance issue would become a problem.For example, Redux is usually used for a single global state,and React-Redux provides a selector interface to solve the performance issue.Selectors are useful to structure state accessor,however, using selectors only for performance wouldn't be the best fit.Selectors for performance require understanding object referenceequality which is non-trival for beginners andexperts would still have difficulties for complex structures.

React Tracked is a library to provide so-called "state usage tracking."It's a technique to track property access of a state object,and only triggers re-renders if the accessed property is changed.Technically, it uses Proxies underneath, and it works not only forthe root level of the object but also for deep nested objects.

Prior to v1.6.0, React Tracked is a library to replace React Contextuse cases for global state. React hook useContext triggers re-renderswhenever a small part of state object is changed, and it would causeperformance issues pretty easily. React Tracked provides an APIthat is very similar to useContext-style global state.

Since v1.6.0, it provides another building-block APIwhich is capable to create a "state usage tracking" hooksfrom any selector interface hooks.It can be used with React-Redux useSelector, and any other librariesthat provide useSelector-like hooks.

Install

This package requires some peer dependencies, which you need to install by yourself.

npm install react-tracked react scheduler

Usage

There are two main APIscreateContainer andcreateTrackedSelector.Both take a hook as an input and return a hook (or a container including a hook).

There could be various use cases. Here are some typical ones.

createContainer / useState

Define auseValue custom hook

import{useState}from'react';constuseValue=()=>useState({count:0,text:'hello',});

This can be useReducer or any hook that returns a tuple[state, dispatch].

Create a container

import{createContainer}from'react-tracked';const{ Provider, useTracked}=createContainer(useValue);

useTracked in a component

constCounter=()=>{const[state,setState]=useTracked();constincrement=()=>{setState((prev)=>({      ...prev,count:prev.count+1,}));};return(<div><span>Count:{state.count}</span><buttontype="button"onClick={increment}>        +1</button></div>);};

TheuseTracked hook returns a tuple thatuseValue returns,except that the first is the state wrapped by proxies andthe second part is a wrapped function for a reason.

Thanks to proxies, the property access in render is tracked andthis component will re-render only ifstate.count is changed.

Wrap your App with Provider

constApp=()=>(<Provider><Counter/><TextBox/></Provider>);

createTrackedSelector / react-redux

CreateuseTrackedSelector fromuseSelector

import{useSelector,useDispatch}from'react-redux';import{createTrackedSelector}from'react-tracked';constuseTrackedSelector=createTrackedSelector(useSelector);

useTrackedSelector in a component

constCounter=()=>{conststate=useTrackedSelector();constdispatch=useDispatch();return(<div><span>Count:{state.count}</span><buttontype="button"onClick={()=>dispatch({type:'increment'})}>        +1</button></div>);};

createTrackedSelector / zustand

Create useStore

importcreatefrom'zustand';constuseStore=create(()=>({count:0}));

CreateuseTrackedStore fromuseStore

import{createTrackedSelector}from'react-tracked';constuseTrackedStore=createTrackedSelector(useStore);

useTrackedStore in a component

constCounter=()=>{conststate=useTrackedStore();constincrement=()=>{useStore.setState((prev)=>({count:prev.count+1}));};return(<div><span>Count:{state.count}</span><buttontype="button"onClick={increment}>        +1</button></div>);};

Notes with React 18

This library internally usesuse-context-selector,a userland solution foruseContextSelector hook.React 18 changes useReducer behavior whichuse-context-selector depends on.This may cause an unexpected behavior for developers.If you see moreconsole.log logs than expected,you may want to try puttingconsole.log in useEffect.If that shows logs as expected, it's an expected behavior.For more information:

API

docs/api

Recipes

docs/recipes

Caveats

docs/caveats

Related projects

docs/comparison

https://github.com/dai-shi/lets-compare-global-state-with-react-hooks

Examples

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

PORT=8080 pnpm run examples:01_minimal

and openhttp://localhost:8080 in your web browser.

You can also try them directly:01020304050607080910111213

Benchmarks

Seethis for details.

Blogs

About

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

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • TypeScript89.0%
  • JavaScript11.0%

[8]ページ先頭

©2009-2025 Movatter.jp