A simple and predictable state management for React and React Native Applications.
- Easy to use and to maintain state management on a React Application.
- Scalable
- Easy to organize
- Compatible with Hooks and Class based Components.
Inspired by:
- Flux State Management flux-state Library
- React bindings for Flux State Management react-flux-state Library
- RXJS rxjs Library
- Recoil State Management recoil Library
- Run on your terminal the following command:
$ npm i --save @cobuildlab/react-simple-state- To import the library anywhere you would like to use it:
import{createEvent,useSubscription,useEvent,View,}from'@cobuildlab/react-simple-state';| Object | Description |
|---|---|
EventParams | Params for the createEvent function. |
createEvent | Helper function to create state events. |
View | Subclass of React.View that includes a this.subscribe method to subscribe to changes on an Event. |
useSubscription | A hook for subscribe to specific events with a callback. |
EventHookParams | Params for the useEvent |
useEvent | A declarative alternative to the useSubscription. |
initialValue- An initial value for the event.reducerA function that mutates the state before it gets propagated.
- Allows you to create a subscribable event.
- The result object can be used for subscriptions with the
Viewor the hooks:useEventanduseSubscription
// agency-events.jsimport{createEvent}from'@cobuildlab/react-simple-state';exportconstOnAgencyList=createEvent();exportconstOnAgencyListError=createEvent();exportconstOnNewAgent=createEvent({initialValue: newAgent(),reducer: (prevState)=>{prevState.agencies=OnAgencyList.get();returnprevState;},});- Allows you to create subscription to events from Class based components
- It handles the subscription lifecycle: subscribe and unsubscribe on react lifecycle events.
// AgencyView.jsimport{View}from"@cobuildlab/react-simple-state";import{OnAgencyList,OnNewAgent}from"./agency-events.js"classAgencyViewextendView{componentDidMount(){this.subscribe(OnAgencyList,(state)=>{// So something with the state.})this.subscribe(OnNewAgent,(state)=>{// So something with the state.})}}- It subscribes a
callbackto an Event from functional components using hooks. - It handles the subscription lifecycle
// AgencyView.jsimport{useSubscription}from"@cobuildlab/react-simple-state";import{OnAgencyList,OnNewAgent}from"./agency-events.js"constAgencyView=()=>{useSubscription(OnAgencyList,(state)=>{// Do something with the state});useSubscription(OnNewAgent,(state)=>{// Do something with the state});return();}initialValue- An initial value for the event.reducerA function that mutates the state before it gets propagated.
- It subscribes ton event from functional components using hooks with a declarative approach.
- It handles the subscription lifecycle
- It handles initial values for the events
- It handles a reducer function for the state.
// AgencyView.jsimport{useEvent}from"@cobuildlab/react-simple-state";import{OnAgencyList,OnNewAgent}from"./agency-events.js"constAgencyView=()=>{conststate=useEvent(OnAgencyList);constagent=useEvent(OnNewAgent,{initialValue: {},reducer: (prevState)=>prevState.agent});return();}Let's build a Flux Workflow for authentication
import{createEvent}from'@cobuildlab/react-simple-state';exportconstLogoutEvent=createEvent({reducer: (prevState)=>{localStorage.clear();returnprevState;},});exportconstLoginEvent=createEvent();exportconstPermissionError=createEvent({reducer: (prevState)=>{LogoutEvent.dispatch();returnprevState;},});export{LogoutEvent,LoginEvent,PermissionError};importReactfrom'react';import{LogoutEvent,LoginEvent,PermissionError}from"./agency-events.js";import{View,useSubscription,useEvent}from'@cobuildlab/react-simple-state';// Class BasedclassViewextendsView{constructor(){super();}componentDidMount(){this.subscribe(LoginEvent,(state)=>{// Do something useful with the Event DataconstuserName=state.user.name;this.setState({userName});});// Register some methodthis.subscribe(LogoutEventthis.logOutEvent);}logOutEvent=(state)=>{//DO something with the state or the state of the StoreconststoreState=LogoutEvent.get();}}// or Functional with React HooksconstView=(props)=>{// Set an Initial ValueconstloginState=useEvent(LoginEvent);constuserState=useEvent(LogoutEvent,{reducer:(state)=>state.user});useSubscription(LoginEvent,(state)=>{// setError// toast.error()});return({loginState&&<Useruser={loginState}>})};import{LoginEvent,LogoutEvent}from'./agency-events.js';constauthenticateAction=(username,password)=>{if(username===undefined)returnLogoutEvent.dispatch();letdataToSave={authenticated: true,
username,
password,};LoginEvent.dispatch(dataToSave);};export{authenticateAction};import{createAction}from'@cobuildlab/react-simple-state';import{OnFecthUserEvent,OnFetchUserErrorEvent}from'./events';import{apiClient}from'./api';// single declarition of the async service and the actionexportconstfetchUserAction=createAction(OnFecthUserEvent,OnFetchUserErrorEvent,async(id)=>{constuser=awaitapiClient.fetch({user: id});returnuser;},);// Or we could declare the async service and then use in with diferent actionsexportconstfetchUserService=async(id)=>{constuser=awaitapiClient.fetch({user: id});returnuser;};exportconstfetchMainUserAction=createAction(OnFecthMainUserEvent,OnFetchMainUserErrorEvent,fetchUserService,);exportconstfetchSecondaryUserAction=createAction(OnFecthSecondaryUserEvent,OnFetchSecondaryUserErrorEvent,fetchUserService,);import{useFetchAction}from'@cobuildlab/react-simple-state';import{fetchUser}from'./actions';// UserProfile componentexportconstUserProfile=({ userId, loadingToken })=>{const[user,loadingUser]=useFetchAction(fetchUser,[userId]);// OR... skip the fetch ultil the token loadsconst[user,loadingUser]=useFetchAction(fetchUser,[userId],{skip: loadingToken,});// OR...const[user,loadingUser]=useFetchAction(fetchUser,[userId],{onCompleted: ()=>{toast.success('user fetched');},onError: ()=>{toast.error('Error when fetching user');},});// OR...const[user,loadingUser,{ refetch }]=useFetchAction(fetchUser,[userId],{onCompleted: ()=>{toast.success('user fetched');},onError: ()=>{toast.error('Error when fetching user');},});useSubscription(OnSaveUserEvent,()=>{// refetch the user after saving form for examplerefetch();});return;// profile view};import{useCallAction}from'@cobuildlab/react-simple-state';import{saveUser}from'./actions';// UserProfile componentexportconstUserProfile=({ userId })=>{constuserData=userDataState;const[save,loadingSubmit]=useCallAction(saveUser);// OR...// setup the action, and return a function that will trigger the action when it needed.const[save,loadingSubmit]=useCallAction(saveUser,{onCompleted: ()=>{toast.success('user saved');},onError: ()=>{toast.error('Error when saving user');},});return(<Form><SubmitButtononClick={()=>save(userId,useCallAction)}/></Form>);};- types improvements to be more genereic.
- Add
useCallActionanduseFetchActionhooks to have a better declaritive way to handle promise in components.
- Add
isEmptymethod to event to know if the event has data without to call thegetmethod.
- Add
createActiondecorator
- Cache callback on
useEvent - Cache the callback on
useSubscriptionand add a dependencies parameter. - Remove
RamdaandRxjsas dependencies
- Remove:
receiveLastValuefor theuseQueryhook
- Typos and documentation
- State Draft