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

diegohaz/constate

Repository files navigation

constate logo

Constate

NPM versionNPM downloadsSizeDependenciesGitHub Workflow Status (branch)Coverage Status

Write local state usingReact Hooks and lift it up toReact Context only when needed with minimum effort.


🕹 CodeSandbox demos 🕹
CounterI18nThemingTypeScriptWizard Form

Basic example

importReact,{useState}from"react";importconstatefrom"constate";// 1️⃣ Create a custom hook as usualfunctionuseCounter(){const[count,setCount]=useState(0);constincrement=()=>setCount(prevCount=>prevCount+1);return{ count, increment};}// 2️⃣ Wrap your hook with the constate factoryconst[CounterProvider,useCounterContext]=constate(useCounter);functionButton(){// 3️⃣ Use context instead of custom hookconst{ increment}=useCounterContext();return<buttononClick={increment}>+</button>;}functionCount(){// 4️⃣ Use context in other componentsconst{ count}=useCounterContext();return<span>{count}</span>;}functionApp(){// 5️⃣ Wrap your components with Providerreturn(<CounterProvider><Count/><Button/></CounterProvider>);}

Learn more

Advanced example

importReact,{useState,useCallback}from"react";importconstatefrom"constate";// 1️⃣ Create a custom hook that receives propsfunctionuseCounter({ initialCount=0}){const[count,setCount]=useState(initialCount);// 2️⃣ Wrap your updaters with useCallback or use dispatch from useReducerconstincrement=useCallback(()=>setCount(prev=>prev+1),[]);return{ count, increment};}// 3️⃣ Wrap your hook with the constate factory splitting the valuesconst[CounterProvider,useCount,useIncrement]=constate(useCounter,value=>value.count,// becomes useCountvalue=>value.increment// becomes useIncrement);functionButton(){// 4️⃣ Use the updater context that will never trigger a re-renderconstincrement=useIncrement();return<buttononClick={increment}>+</button>;}functionCount(){// 5️⃣ Use the state context in other componentsconstcount=useCount();return<span>{count}</span>;}functionApp(){// 6️⃣ Wrap your components with Provider passing props to your hookreturn(<CounterProviderinitialCount={10}><Count/><Button/></CounterProvider>);}

Learn more

Installation

npm:

npm i constate

Yarn:

yarn add constate

API

constate(useValue[, ...selectors])

Constate exports a single factory method. As parameters, it receivesuseValue and optionalselector functions. It returns a tuple of[Provider, ...hooks].

useValue

It's anycustom hook:

import{useState}from"react";importconstatefrom"constate";const[CountProvider,useCountContext]=constate(()=>{const[count]=useState(0);returncount;});

You can receive props in the custom hook function. They will be populated with<Provider />:

const[CountProvider,useCountContext]=constate(({ initialCount=0})=>{const[count]=useState(initialCount);returncount;});functionApp(){return(<CountProviderinitialCount={10}>      ...</CountProvider>);}

The API of the containerized hook returns the same value(s) as the original, as long as it is a descendant of the Provider:

functionCount(){constcount=useCountContext();console.log(count);// 10}

selectors

Optionally, you can pass in one or more functions to split the custom hook value into multiple React Contexts. This is useful so you can avoid unnecessary re-renders on components that only depend on a part of the state.

Aselector function receives the value returned byuseValue and returns the value that will be held by that particular Context.

importReact,{useState,useCallback}from"react";importconstatefrom"constate";functionuseCounter(){const[count,setCount]=useState(0);// increment's reference identity will never changeconstincrement=useCallback(()=>setCount(prev=>prev+1),[]);return{ count, increment};}const[Provider,useCount,useIncrement]=constate(useCounter,value=>value.count,// becomes useCountvalue=>value.increment// becomes useIncrement);functionButton(){// since increment never changes, this will never trigger a re-renderconstincrement=useIncrement();return<buttononClick={increment}>+</button>;}functionCount(){constcount=useCount();return<span>{count}</span>;}

Contributing

If you find a bug, pleasecreate an issue providing instructions to reproduce it. It's always very appreciable if you find the time to fix it. In this case, pleasesubmit a PR.

If you're a beginner, it'll be a pleasure to help you contribute. You can start by readingthe beginner's guide to contributing to a GitHub project.

When working on this codebase, please useyarn. Runyarn examples to run examples.

License

MIT ©Diego Haz


[8]ページ先頭

©2009-2025 Movatter.jp