Meiosis Documentation

Table of Contents | Documentation Examples

The Meiosis Pattern Cheatsheet

IMPORTANT NOTE: For a complete explanation of the Meiosis Pattern, please see the Meiosis Tutorial.

Helper functions! Meiosis is a pattern that you can set up yourself, but by popular demand meiosis-setup is now available for your convenience.

This is a quick summary of the Meiosis Pattern:

Here is the code to set up the Meiosis Pattern:

const app = {
  initial: ...,
  Actions: (update, getState) => {
    return ...
  }
};

const update = stream();

// Using Mergerino:
const states = scan(merge, app.initial, update);

// Using Function Patches:
const states = scan((state, patch) => patch(state), app.initial, update);

const actions = app.Actions(update, states);

Then, pass state and actions to views.

Optionally, add Services and Effects:

const app = {
  initial: ...,
  Actions: (update, getState) => {
    return ...
  },
  // services are state => patch
  services: [...],
  // effects are state => {
  //   call update(...) or actions.someAction(...);
  // }
  Effects: (update, actions) => [...]
}

// Using Mergerino:
const accumulator = merge;

// Using Function Patches:
const accumulator = (state, patch) => patch ? patch(state) : state;

const update = stream();

const runServices = startingState =>
  app.services.reduce(
    (state, service) => accumulator(state, service(state)),
    startingState
  );

const states = scan(
  (state, patch) => runServices(accumulator(state, patch)),
  runServices(app.initial),
  update
);

const actions = app.Actions(update, states);
const effects = app.Effects(update, actions);

states.map(state => effects.forEach(effect => effect(state)));

Next, wire up your view.

Using Mithril

const App = {
  view: function({ attrs: { state, actions } }) {
    // render view according to state, call actions to trigger changes
    // pass { state, actions } to other components.
  }
};

m.mount(document.getElementById("app"), {
  view: () => m(App, { state: states(), actions })
});

states.map(() => m.redraw());

Using React

import React from "react";

const App = ({ states, actions }) => {
  const [init, setInit] = React.useState(false);
  const [state, setState] = React.useState(states());

  if (!init) {
    setInit(true);
    states.map(setState);
  }

  // render view according to state, call actions to trigger changes
  // pass state={state} actions={actions} to other components.
  return (<div>...</div>);
};

ReactDOM.render(<App states={states} actions={actions} />,
  document.getElementById("app"));

Using Preact

import { useState } from "preact/hooks";

const App = ({ state, actions }) => {
  const [init, setInit] = useState(false);
  const [state, setState] = useState(states());

  if (!init) {
    setInit(true);
    states.map(setState);
  }

  // render view according to state, call actions to trigger changes
  // pass state={state} actions={actions} to other components.
  return (<div>...</div>);
};

preact.render(<App states={states} actions={actions} />,
  document.getElementById("app"));

Using lit-html

const App = ({ state, actions }) => {
  // render view according to state, call actions to trigger changes
  // pass { state, actions } to other view functions.
};

const element = document.getElementById("app");
states.map(state => render(App({ state, actions }), element));

Components

To use multiple instances of a component, or to specify the state property outside of a component, pass an id along with state and actions to views. Use state[id] to read the component's state, pass the id to actions, and use the id in actions to issue patches that update the corresponding state property.

See the Components section of the Meiosis Tutorial for a complete explanation.

Table of Contents | Documentation Examples


Meiosis is developed by @foxdonut00 / foxdonut and is released under the MIT license.