Hover-Engine
A state-management library that runs on predictable magic.
You've got to have POWER!
Hover-Engine is inspired by minidux, hover, and hyperapp so if you're familar with those frameworks, you'll notice some similarities!
Hover-Engine gives your app the following super-powers:
- Trigger multiple sets of actions with a single dispatch!
- Notify as many listeners as you want!
- Handle async (or chained) action calls with predictable results!
- No Dependencies!
- Light enough to give you flight (~2 KB)!
Install
You can install hover-engine with npm like any other package.
npm install --save hover-engine
You can also include the umd distributable in your webpage directly with a script tag.
Usage
const HoverEngine = const counterActions = 0 state + 1 const engine = engineengine engineactions // -> NEW STATE: { counter: 1 }engineactions // -> NEW STATE: { counter: 2 }enginestorecounter // -> 2
API
constructor()
The constructor builds a new HoverEngine object. It takes in no parameters, and is immediately available for calling actions and store on (although they will be empty until you add actions).
Usage:
const engine =
addActions(actionGroups)
The addActions
function adds new actions to the HoverEngine. It takes in a single object, whose keys will be used to get at the store, and whose values is an object mapping action names to functions.
Example actionGroup:
const actionGroup = counter: 0 counter + 1 counter - 1
In this example, counter
is the key which you can use on the engine.store
. The actions: init
, increment
, and decrement
, are functions which will be called in engine.actions
const engine = engine // adds the counter action groupengineactions // calls our increment function for counterenginestorecounter // returns the value at counter (in this case, 1)
init
action
The const actionGroup = counter: 0
All groups of actions must include the init
action. This action dictates the initial state of the store value for those actions. In the above example, you'll notice that we set the initial value to 0. It is common to use zero, empty array, or empty string as inital values, but it is also a good place for default values.
The init
action is called after engine.addActions
runs. It is passed no arguments.
Action Arguments
const temperatureActions = 70 temp + 1 newTemp { }
Excluding the init
action, all actions are provided with the following arguments:
- current state of the store (for this group of actions)
- value passed into the action call
- actions from the Hover-Engine
The first argument allows you to build a new state off of the existing one. In the example above, we increaseTemp
from the value currently in the store.
const engine = engineengineactionsconsole // -> { temp: 71 }
The second argument is anything that we pass in when we call the action. For example:
const engine = engineengineactionsconsole // -> { temp: -10 }
In this example, we would set temperature -10
to the current value in the store.
The third argument is a reference to all available actions in Hover-Engine. These actions can be called and then are added to an existing queue of actions that get fired off one at a time to update the store.
const engine = engineengineactionsconsole // -> { temp: 76 }
This can be useful for async actions such as fetching, or when you need to call an action as a result of another action.
Adding Multiple Action Groups
With Hover-Engine, you can add multiple action groups two different ways. One way is by calling addActions
multiple times. The other way, is by providing multiple sets of actions in the object you pass in, as shown below.
const todoActions = todo: todos input: '' newInput '' const engine = engine // adds the todo and input action groupsconst newTodo = 'Buy Milk'engineactions // store -> { todo: [], input: 'Buy Milk' }engineactions // store -> { todo: ['Buy Milk'], input: '' }
You'll notice in the above example that calling addTodo
actually called both todo's addTodo
and input's addTodo
. We'll go over this more in the engine.actions section below.
addListener(listener)
Listeners in Hover-Engine are functions that get called whenever an action is called. It receives the updated engine.store
, engine.actions
, as well as information about the action that was called (read below).
const commentThreadActions = thread const engine = engine engine
Like addActions
, you can add as many listeners as you want by calling addListener
multiple times. Each will be called with the new store.
Listener Arguments
Along with the store and actions, listeners also recieve the name of the action that was called, and the argument it was called with. With these, you can use listeners to debug what is happening in hover-engine. In the example below, we log the action and the new values in the store.
const debugListener = { console}
notifyListeners(actionName, actionArguments)
notifyListeners
is a function which tells all the listeners to be triggered. It takes in an action name and action argument (both of which are optional), and calls all the listeners that have been added with the current store and actions, and passes along the action name and argument if they were included. You shouldn't need this in most applications, but can be useful for testing or debugging your logic.
const counterActions = 0 counter + 1 const engine = engineengine // store: {counter: 0}
Like addActions
, you can add as many listeners as you want by calling addListener
multiple times. Each will be called with the new store.
engine.actions
As shown above in the various examples above, engine.actions
provides a means to call any actions that were added via addActions
off of engine. In addition, actions
is automatically a composition of all same-named actions.
const TimeZoneActions = {status: 'NOT_LOADED' timezone: null} {status: 'LOADED' timezone: newTimezone} { } { actions } const WeatherActions = {status: 'NOT_LOADED' weather: null} {status: 'LOADED' weather: newWeather} { } { actions } const engine = engine engineactions
In the example above, same-named actions like updateZipCode
will fire off for both the WeatherActions
and the TimeZoneActions
. It queues up weather.updateZipCode
and timezone.updateZipCode
. As both of those resolve, any actions that are triggered (like getWeatherFromZipCode
and setWeather
) will also get added to the queue in order, and each will take in an updated version of the state.
engine.store
The engine store exposes the current state of all the action groups. When you addActions
the keys of the action object are the accessors for store values.