0.0.3 • Published 8 years ago

fluxlet v0.0.3

Weekly downloads
4
License
MIT
Repository
github
Last release
8 years ago

Build Status npm version Dependency Status devDependency Status Code Climate License

Fluxlet

Fluxlet is a micro-framework for managing state within your application.

Its focus is on the predictable uni-directional flow of immutable data within a single round of the event loop.

Overview

Data comes in from an event, an action is dispatched which updates the state, which can then flow through a series of calculations which perform further updates of the state, and finally into a bunch of side-effects which do stuff with the resulting state.

This diagram illustrates the flow of data through a Fluxlet...

Fluxlet data flow

The lines represent the actual flow of data, green is data from the event, and red is the state. The shaded rectangles are functions.

Why?

The whole point of this is that from any action dispatch (knowing the payload and starting state), you should be able to reason about (and reliably test) the end state, and know exactly what side-effects should be performed. You should be able to reason about the exact state of your application and what async tasks it's performing at any time.

The Component Functions

An action is a pure function that takes a payload and a state and returns a new state.

I lied a little, an action function actually takes the payload and returns another function that takes the state, the reasons for this become clear when you create actions using immutable state update functions.

The new state from the action is passed into a chain of calculations, which are also pure functions that take state and return new state.

The state from the last calculation is then passed into all of the side-effects, which are functions that take the state and do stuff, eg. render to DOM, make requests, but they can't directly affect the state.

For the sake of clarity, there is some detail missing from the diagram above: The initial state is also passed to every calculation and side-effect so that they can compare the current state to the previous state to determine if they actually need to do anything. This previous state should be used simply for comparison purposes.

An overview of the component function signatures:

  • action: (...payload) -> (initial-state) -> transient-state
  • calculation: (transient-state, initial-state) -> transient-state
  • side effect: (final-state, initial-state, dispatchers) -> void

The state from the final calculation in the chain (or the action if no calculations are called) becomes the final state

You explicitly register these component functions with a Fluxlet using its fluent API at construction time.

Dispatchers

Fluxlet creates a separate dispatcher function for every action, but they all call a shared set of calculations and side-effects.

It's these dispatcher functions that are called from async event handlers, or other fluxlets.

One Big Immutable State

State within a Fluxlet is a single immutable JS object, the state must NEVER be modified by a component function. Actions and calculations must either return the same unmodified state or a new version of the state.

TODO: Could do with a reference to how immutable data structures work here

The Rules

Action and calculation functions must be pure referentially transparent functions, that is, they can use data given to them and should return a consistent state from the data passed in - they MUST NEVER use data from elsewhere or perform any side-effects.

Side-effects on the other hand, as the name suggests can perform side-effects, but they can not alter state or directly dispatch another action. They can however call an action dispatcher from within an async event handler, eg. timeout, ajax callback.

A side-effect should do as little as possible, delegating any data processing to a calculation wherever possible. It should also source any transient data from the state and not directly from the DOM, ie. form values should be fed into the state via an action. Keeping the state as the authoritative state of the application at any time. Although it may check the DOM to determine whether it needs to update it or not.

Example

import fluxlet from "fluxlet"
import { update } from "fluxlet-immutable/update"

export default function() {
  fluxlet('hello-world')
    .state({
      name: '',
      response: ''
    })
    .actions({ setName })
    .calculations({ formulateResponse })
    .sideEffects({ deliverResponse })
    .init(bindGlobalEvents)
}

function bindGlobalEvents(dispatch) {
  document.getElementById("id")
    .addEventListener("input", (event) => dispatch.setName(event.target.value))
}

// Actions
const setName = (name) => update('name', name)

// Calculations
const formulateResponse = update('response', (x, state) => `Hello ${state.name}`)

// Side-Effects
const deliverResponse = (state) => {
  document.getElementById("out").textContent = state.response
}

This example uses the update function from the fluxlet-immutable library, which is in a separate package as you may want to use whatever immutable library you prefer.

For a richer example see the fluxlet-example-todomvc.

Oh and btw, all of the Fluxlet code, additional libraries and examples are written and take advantage of ECMAScript 2015 syntax, but only use API features from ES5.

Documentation

Read the fluxlet source source, and/or the groc generated docs.

Docs can be generated using groc:

$ groc

And then opened directly from the filesystem in a browser.

Installing

Using jspm

$ jspm install fluxlet=github:fluxlet/fluxlet@master

Using npm

$ npm install fluxlet

Using bower

$ bower install fluxlet/fluxlet

You'll find the ES6 src in bower_components/fluxlet/src/fluxlet.js, which will need to be transpiled using your favourite tools.

Testing Fluxlets

To make testing of fluxlets easier a test library, testlet, provides a fluent API for setting up fluxlets, dispatching actions, and checking state using a given/when/then style.

Development

$ npm install

Tests

Test are run using karma and jspm:

$ npm test

or

$ jspm install
$ karma start

There is also a config for Wallaby if you have it installed in your IDE.

0.0.3

8 years ago

0.0.2

8 years ago

0.0.1

9 years ago