Skip to content

cefn/lauf

Repository files navigation

Logo - Image of Runner

Lauf

Logo - Diego Naive, Noun Project.

Lauf strictly isolates business logic and state management from UI.

It uses a normal Javascript object as a central, reactive Store.

Lauf business logic is explicit, predictable, testable - like a Redux app, but without the boilerplate.

Getting started

In the example code below, logic.js defines state and state change definitions while ui.js uses those definitions, to create a Counter app.

The Display automatically re-renders whenever the counter changes. The Increment and Decrement buttons are never re-rendered, but they trigger state changes on user input.

// logic.js
export const INITIAL_STATE = {
  counter: 0,
};

export const increment = (draft) => (draft.counter += 1);

export const decrement = (draft) => (draft.counter -= 1);
// ui.js
import React from "react";
import { useSelected, useStore } from "@lauf/store-react";
import { INITIAL_STATE, increment, decrement } from "./logic";

const Display = ({ store }) => {
  const counter = useSelected(store, (state) => state.counter);
  return <h1>{counter}</h1>;
};

const Increment = ({ store }) => (
  <button onClick={() => store.edit(increment)}>Increase</button>
);

const Decrement = ({ store }) => (
  <button onClick={() => store.edit(decrement)}>Decrease</button>
);

export const App = () => {
  const store = useStore(INITIAL_STATE);
  return (
    <>
      <Display store={store} />
      <Increment store={store} />
      <Decrement store={store} />
    </>
  );
};

You can experiment with the Counter app running in a sandbox; (javascript version), (typescript version).

A more complex business logic example is the NextJS Snake app. An example incorporating an network API and local cache is our clone of the Redux Async example. An event queue example is the Color Mixer.

Our interactive demos use @lauf/store-react bindings. However, Lauf has no React dependencies and can be used server side or in any other UI Framework using @lauf/store and @lauf/store-follow

API Overview

To wire changing state to business logic, use Store Follow to queue up state-changes for your handlers.

To wire changing state to UI, use Store React to refresh components only when their bound state changes.

Lauf utilities include a Store for state, a Message Queue for events and a Mutex or Lock to control resource-sharing.

To find out more, visit the API

Lauf vs Redux

Flux-based frameworks like Redux or React.useReducer will guide you to use an action type, a structured payload definition, probably an Action creator, possibly a thunk creator, with the result sent via a dispatcher to (hopefully) line up with corresponding behaviour in a reducer and probably some middleware.

Lauf aims to avoid all this. Your coding style with Lauf remains simple, procedural and explicit.