- Notifications
You must be signed in to change notification settings - Fork0
dev-afzalansari/react-tivity
Folders and files
| Name | Name | Last commit message | Last commit date | |
|---|---|---|---|---|
Repository files navigation
State solution for React
npm i react-tivity
yarn add react-tivity
Easy andSmall state management library forReact with hooks based api and zero configuration. Withreact-tivity you don't need to pass the selector in the hook you get the whole state that you can destructure and your components will get updated only when the value they are consuming is changed.
- Zero boilerplate.
- Zero configuration
- Small & Easy.
- Hooks based Api.
- Typescript Support.
create takes anobject orinitializer and returns a hook to be used in components.
import{create}from'react-tivity'
Then initialize store by passingobject orinitializer
constuseCount=create({count:0,inc:state=>state.count++,dec:state=>state.count--})
Usage in react component
functionCounter(){let{ count, inc, dec}=useCount()return(<div><h1>{count}</h1><buttononClick={inc}>Count++</button><buttononClick={dec}>Count--</button></div>)}
Someapis are assigned to the hook and can be used in or outside of react component.
// you can get access to state objectletcount=useCount.state// calling methodscount.inc()count.dec()// reading valuescount.count// or setting valuescount.count++// subscribeletcallback=()=>console.log('count changed')letunsubscribe=useCount.subscribe(callback)// will log 'count changed' every time state value changes// to unsubscribe call the variable you assigned subscription tounsubscribe()
reduce takes areducer function as first argument andobject orinitializer which returns anobject as second argument. You can pass your stateobject without any method and retrieve dispatch function assigned tohook itself as method.
import{reduce}from'react-tivity'
Then initialize store by passingreducer &object orinitializer as second.
functionreducer(state,action){switch(action.type){case'inc':return{count:state.count+1}case'dec':return{count:state.count-1}}throwError('unknown action type')}constuseCount=reduce(reducer,{count:0})
Usage in react component.
functionCounter(){let{ count,dispatch:countDispatch}=useCount()return(<div><h1>{count}</h1><buttononClick={()=>countDispatch({type:'inc'})}>Count++</button><buttononClick={()=>countDispatch({type:'dec'})}>Count--</button></div>)}
Someapis are assigned to the hook and can be used in or outside of react component.
// all apis from create such as subscribe and state object are assigned// dispatchletdispatch=useCount.state.dispatchdispatch({type:'inc'})dispatch({type:'dec'})
persist works same ascreate if only one argument is passed if passed two arguments firstreducer and secondobject it acts as reduce. It takes an additional propertyconfig which won't be saved as a state value. It will persist your stateobject in either storage created by itself or the custom storage you provide. It accepts asynchronous storage only, but for convenience you can pass 'local' or 'session' to create asynhronous localStorage & asyncronous sessionStorage respectively.
import{persist}from'react-tivity'
Then initialize store by passingobject orinitializer
// acts as createconstuseCount=persist({count:0,inc:state=>state.count++,dec:state=>state.count--,config:{key:'@count'// required,storage:'session'// defaults to 'local'}})// acts as reduceconstuseCount=persist(reducer,{count:0,config:{key:'@count',storage:'session'// defaults to 'local'}})
constuseStore=persist({// First argument reducer you want it to act as `reduce` and then `object` or `initializer`// ...config:{// Only required property of configkey:'string',// Any asynchronous storage which has setItem, getItem and removeItem properties, defaults to 'local' can also accept 'session'storage:'local'|'session'|AsyncStorage,// To serialize the data to be saved in chosen storage, defaults to JSON.stringify()serialize:(state)=>JSON.stringify(state),// To deserialize saved data when retrieved from chosen storage, defaults to JSON.parse()deserialize:(state)=>JSON.parse(state),// An array of state slices not to save for eg. ['count'], defaults to []blacklist:[],// Required if you change your structure of your state otherwise optional, defaults to 0version:0,// Required if you have changed version, So you can migrate your previously saved state values to current one. defaults as below.migrate:(current,previous)=>current}})// More on migrate, In order to migrate between version change// You receive Current State & Previous State so you can decide what to keep what to throw, eg. belowconstmigrate=(curr,prev)=>{if(prev.version===0){current.upvotes=prev.likes// Current state's `upvotes` slice will get hydrated with value previous state's `likes`returncurrent// Return current now}}
Asynchronous storages will hydrate stores asynchronously it means that user can have a flash of initial state before storegets hydrated and the view gets updated. To overcome this problem a_status slice is managed internally. The value of_statusisfalse initially and when asynchronous task gets done it is set totrue so you can wrap your child components consumingthat state in a parent wrapper component to prevent flash of that initial state by rendering a loader component until store getshydrated.
// Note: `_status` property gets set to true even if there was no state saved in the storage.functionPersistWrapper(){let{ _status}=useCount()if(!_status)return<h1>Loading...</h1>return<ChildComponent/>}functionChildComponent(){// child component consuming useCount's state}
Someapis are assigned to the hook and can be used in or outside of react component.
// all apis from `create` and `reduce`// persistletpersist=useCount.persist// or just useCount.persist.clearStorage()persist.clearStorage()// clears the storage assigned to useCount
typeState={count:number;inc:(state:State)=>void;dec:(state:State)=>void;}constuseCount=create<State>({count:number,inc:(state)=>state.count++,dec:(state)=>state.count--})
typeState={count:number;}typeAction={type:string;}functionreducer(state:State,action:Action){//....}constuseCount=reduce<State,Action>(reducer,{count:0,})
If using ascreate same ascreate just add config.
typeState={count:number;inc:(state:State)=>void;dec:(state:State)=>void;config:{key:string;storage:string;}}constuseCount=create<State>({count:number,inc:(state)=>state.count++,dec:(state)=>state.count--,config:{key:'@count',storage:'session',}})
If using asreduce.
typeState={count:number;config:{key:string;storage:string;}}typeAction={type:string;}functionreducer(state:Omit<State,'config'>,action:Action){//....}// Pass second generic argument as true if you are using persist as reduceconstuseCount=reduce<State,true,Action>(reducer,{count:0,config:{key:'@count',storage:'session'}})
Licensed underMIT License
About
State solution for React
Topics
Resources
License
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Releases
Packages0
Uh oh!
There was an error while loading.Please reload this page.