/little-state-machine

📠 React hooks for persist state management

Primary LanguageTypeScriptMIT LicenseMIT

Little State Machine - React Hooks for state management

♆ Little State Machine

State management made super simple

Tweet  npm downloads npm

✨ Features

  • Follow flux application architecture
  • Tiny with 0 dependency and simple (less than 1kb)
  • Persist state by default (sessionStorage)
  • Build with React Hooks
  • Compatible with React Native

📦 Installation

$ npm install little-state-machine

🖥 Demo

Check out the Demo.

🕹 API

🔗 StateMachineProvider

This is a Provider Component to wrapper around your entire app in order to create context.

🔗 createStore
createStore(store, options?: {
 name: string; // rename the store
 middleWares?: Function[]; // function to invoke each action
 syncStores?:  // sync with external store in your session/local storage
    | Record<string, string[]>
    | { externalStoreName: string; transform: Function } // name of the external store, and state to sync
    | { externalStoreName: string; transform: Function }[];
}})

Function to initialize the global store, invoked at your app root (where <StateMachineProvider /> lives).

import yourDetail from './state/yourDetail';

function log(store) {
  console.log(store);
}

createStore({
  yourDetail, // it's an object of your state { firstName: '', lastName: '' }
}, {
  middleWares: [log], // an array of middleWares, which gets run each actions
  syncStores: { // you can sync with external store and transform the data
    externalStoreName: 'externalStoreName',
    transform: ({ externalStoreData, currentStoreData }) => {
      return { ...externalStoreData, ...currentStoreData };
    },
  }
  // alternative you can just specify the store name and root state name { yourDetails: { firstName: '' } }
  // syncStores : {
  //   externalStoreName: ['yourDetail'],
  // }
  // or you can pass in an array of transform function
  // syncStores : [
  //   { 
  //     externalStoreName: 'externalStoreName',
  //     transform: ({ externalStoreData, currentStoreData }) => {
  //       return { ...externalStoreData, ...currentStoreData };
  //     },
  //   }
  // ]
})
🔗 useStateMachine

This hook function will return action/actions and state of the app.

import { updateUserNameAction, removeNameAction } from './actions/yourDetails';

const { action, state } = useStateMachine(updateUserNameAction);
const { actions, state } = useStateMachine({
  removeNameAction,
  updateUserNameAction
});

// The following examples are for optional argument
const { actions, state } = useStateMachine({
  removeNameAction,
  updateUserNameAction
}, {
  removeNameAction: 'removeName',
  updateUserNameAction: 'updateUserName',
});
const { action, state } = useStateMachine(updateUserNameAction, {
  shouldReRenderApp: false // This will prevent App from re-render and only update the store 
});

âš’ DevTool

Built-in DevTool component to track your state change and action.

<StateMachineProvider>
 {process.env.NODE_ENV !== 'production' && <DevTool />}
</StateMachineProvider>

📖 Example

📋 app.js

import React from 'react'
import yourDetail from './yourDetail'
import YourComponent from './yourComponent'
import { StateMachineProvider, createStore, DevTool } from 'little-state-machine'

// The following code is for React Native usage
// import { AsyncStorage } from "react-native";
// setStorageType(AsyncStorage);

// create your store
createStore({
  yourDetail,
});

export default () => {
  return (
    <StateMachineProvider>
      {process.env.NODE_ENV !== 'production' && <DevTool />}
      <YourComponent />
    </StateMachineProvider>
  )
}

📋 yourComponent.js

import React from 'react'
import { updateName } from './action.js'
import { useStateMachine } from 'little-state-machine'

export default function YourComponent() {
  const {
    action,
    state: { yourDetail: { name } },
  } = useStateMachine(updateName);

  return <div onClick={() => action({ name: 'bill' })}>{name}</div>
}

📋 yourDetail.js

export default {
  name: 'test',
}

📋 action.js

export function updateName(state, payload) {
  return {
    ...state,
    yourDetail: {
      ...state.yourDetail,
      ...payload,
    },
  }
}

🛠 Window Object

🔗 window.STATE_MACHINE_DEBUG

This will toggle the console output in dev tool.

window.STATE_MACHINE_DEBUG(true) to turn debug on in console

window.STATE_MACHINE_DEBUG(false) to turn off debug on in console

🔗 window.STATE_MACHINE_RESET

This will reset the entire store.

window.STATE_MACHINE_RESET() to reset the localStorage or sessionStorage

🔗 window.STATE_MACHINE_GET_STORE

This will return the entire store.

window.STATE_MACHINE_GET_STORE()

🔗 window.STATE_MACHINE_SAVE_TO

Save into another session/local storage

window.STATE_MACHINE_SAVE_TO(name: string)

🔗 window.STATE_MACHINE_LOAD

Load saved state into your app, you can either supply a name of your session/local storage, or supply a string of data.

window.STATE_MACHINE_LOAD({ storeName?: string, data?: Object })

storeName: external session/local storage name

data: string of data

Contributors

Thanks goes to these wonderful people: