Thanks to visit codestin.com
Credit goes to github.com

Skip to content
/ substate Public

pub/sub state management with optional deep cloning

License

tamb/substate

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

SubState

The Problem

State management with Redux is really nice. It's also nice with Vuex. But it's lacking in filtering. When using a Pub/Sub you can filter by "topic" or by "content" but you can easily lose track of events being fired. Well it's hybrid time!

Purpose

  • To manage state with a simple PubSub pattern
  • To use the simplicity of Flux
  • For State to return a new state (pure function)
  • Message filtering can be applied without a switch statement (you create your own event $type)
  • To allow for manipulation of deeply nested state properties through use of strings {'my[index]deeply.nests.state': 'new value'} (we're sending this to SubState to not mutate the state, but make a new copy (Flux-y)!
  • Maintain a small size relative to deep cloning (13kb! minified, 4kb gzipped)!

note: anything marked | no docs | means I haven't documented it yet.

Contents

  1. How it Works

  2. Demos

  3. Installation

  4. Instantiation

  5. Options

  6. State Methods

  7. Event Methods

  8. State Events

  9. Custom Events

  10. Usage with React

  11. Updates to Come

  12. Pull Requests

How it Works

The Steps

  1. (if using modules) import { myInstance } from 'myFile'
  2. Components will register one or more methods to rerender themselves using your instance (see instantiation) using myInstance.on('STATE_UPDATED', rerender) per method
  3. Components take UI event ("click", "focus", etc) and pass it off to a Handler/Reducer
  4. The Handler/Reducer figures out what should change in the state (it does not update the state directly). It also figures out if/what $type should be sent to the Pub/Sub module
  5. The Handler/Reducer will then emit UPDATE_STATE to the Pub/Sub module
  6. The Pub/Sub module will create a new state and will emit STATE_UPDATED or the specified $type to the Components.
  7. The Components will digest the new State using the method(s) registered in step 2
  8. If you want a deep clone pass in $deep: true into the state on emit. OR defaultDeep: true in the options.

Demos

Installation

  • npm install substate --save
  • copy and paste from index.js into a <script> or external js file

Instantiation

SubState is a class so you call it like so

myFile.js

import SubState from 'substate';

Then you instantiate it as such

export const myInstance = new SubState({options});

Options

Substate accepts an options object as an optional parameter. These are the possible options

Option Desc Default
name name of the instance 'SubStateInstance'
currentState index of state to start on 0
stateStorage array of all the states [ ]
state object containing the initial state null
defaultDeep default to deep cloning the state everytime false
beforeUpdate middleware for before state is updated. Has access to substate instance null
afterUpdate middleware for after state is updated. Has access to substate instance null

State Methods

  • @param optional method parameter
  • @param* required method parameter
Method Desc Returns
getState get a state @param* - index of state needed state
getcurrentState get the current state current state object
getProp get a prop from current state @param* - string path to prop property you request
changeState change the version of the state @param* - {requestedState: index of state, action: (optional name of event to emit)} emits action parameter event or 'STATE_CHANGED' event with the new current state
resetState resets the stateStorage array to an empty array emits 'STATE_RESET'

Event Methods

  • @param optional method parameter
  • @param* required method parameter
  • @param[num] order of method parameter
Method Desc
on @param1* STRING of event name to listen to. @param2* FUNC handler to execute when this event you listen to happens
off @param1* STRING of event name to remove handler from. @param2* FUNC to remove from the execution queue
emit @param1* STRING event name @param2 object of data to pass into your handler event from 'on' method

State Events

Event Desc Returns
'UPDATE_STATE' updates the entire state with the object passed in updated state
'CHANGE_STATE' fires changeState method above requires same @params emits 'STATE_CHANGED'

Custom Events

note: the object of data that is passed, cannot have a key called '$type'

Method Event Custom Event Next
emit 'UPDATE_STATE' @param2 is an object: {$type: 'MY_CUSTOM_EVENT'} Will update/change state. The $type property will then be emitted so you can listen to it like SubStateInstance.on('MY_CUSTOM_EVENT', func)

To clear this ^ up :

Basically to utilitze a custom event, you still need to use UPDATE_STATE but the data object needs a $type with an event name you want the State to emit when updated

Usage with React

Use the package substate-connect and it wires up just like redux does with React.

a few thoughts on the overall react-redux architecture:

Currently most of us do this:

// MyComponent.js

export default connect(mapStateToProps)(MyComponent)

This is done in the component file itself! That should raise a red flag. Suddenly you're making your component (the thing that should be reusable) literally mapped to the state of this app! So I have a suggestion:

Do this:

// MyComponent.js

export default MyComponent;
// App specific view or where my components are used for purposeful composition

import MyComponent from './components/MyComponent';
import mySubStateInstance from './state.js';
import { connect } from 'substate-connect';

const WiredMyComponent = connect(mySubStateInstance, MapStateToProps)(MyComponent);

... inside some render function
   <WiredMyComponent />

Updates to come

  • Stripping $from all class methods
  • deep cloning option
  • remove localstorage feature
  • remove UPDATE_CHUNK
  • Jest tests for pubsub module
  • Jest tests for substate module
  • Make compatible with NodeJS AND browser
  • find smaller deep clone dependency
  • utilize newer version of object-bystring
  • create module support for merging different state instances,
  • global hooks
  • better dev instructions and console warnings/errors
  • seemless compatibility with infernojs, preactjs, stenciljs
  • demos demos demos

About

pub/sub state management with optional deep cloning

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •