0.1.3 • Published 7 years ago

web-machine v0.1.3

Weekly downloads
2
License
MIT
Repository
github
Last release
7 years ago

Web-Machine

js-semistandard-style

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 });