web-machine
v0.1.3
Published
A state-machine inspired library for managing web apps
Downloads
8
Maintainers
Readme
Web-Machine
Web-Machine is a Redux alternative. Like Redux, Web-Machine is inspired by the Elm architecture. Web-Machine replaces Middleware and Thunks with subscriptions.
Subscriptions, informed by State Machine theory, allow side effects to be loaded onto specific transitions in your app state, rather than loaded onto actions, agnostic to state (e.g. redux-saga).
Installation
npm install --save web-machine
yarn add web-machine
Concepts
Subscriptions
Subscriptions are inspired by Elm Ports.
When you initialize a Web-Machine program, you may register any number of subscriptions. A subscription in Web-Machine is just a function. Each subscription accepts Commands (think redux actions), and a dispatch function. It may then do any side effects you wish, and dispatch Actions back to the Web-Machine program.
Commands vs Actions
In Web-Machine, we use the terms Command and Action to refer to very similar concepts. Commands and Actions have the same API. Each is simply a plain JavaScript object with the following shape:
{ type: string; body: any; }
The only difference is in semantic: Commands are sent to subscriptions, while Actions are sent to the update function (analogous to Redux's reducer).
Usage
An example of usage, ripped shamelessly from my own fledgling project:
https://github.com/ajhyndman/website
// @flow
import React from 'react';
import ReactDOM from 'react-dom';
import styled from 'styled-components';
import { Program } from 'web-machine';
import { assoc } from 'ramda';
import NewsFeed from 'components/NewsFeed';
const Title = styled.h1`
font-size: 2em;
`;
const Container = styled.div`
text-align: center;
padding: 1rem;
`;
const init = [
{
title: 'New York Times Headlines',
news: []
},
{ type: 'FETCH_NEWS' }
];
const subscriptions = [
(command, dispatch) => {
switch (command.type) {
case 'FETCH_NEWS':
window.fetch('https://api.rss2json.com/v1/api.json?rss_url=http%3A%2F%2Frss.nytimes.com%2Fservices%2Fxml%2Frss%2Fnyt%2FHomePage.xml')
.then((response) => response.json())
.then((responseJson) => {
dispatch({
type: 'UPDATE_NEWS',
body: responseJson.items
});
});
break;
default:
return;
}
}
];
const update = (action, model) => {
switch (action.type) {
case 'UPDATE_NEWS':
return [assoc('news', action.body, model)];
case 'FETCH_NEWS':
return [model, { type: 'FETCH_NEWS' }];
default:
return [model];
}
};
const view = (model, dispatch) => {
ReactDOM.render(
<Container>
<Title>{model.title}</Title>
<NewsFeed news={model.news} />
<button onClick={() => dispatch({ type: 'FETCH_NEWS' })}>Update News</button>
</Container>,
document.querySelector('#app')
);
};
export default new Program({ init, subscriptions, update, view });