Skip to content

A JavaScript side effect management library based on finite state machines

Notifications You must be signed in to change notification settings

8coon/automatons

Repository files navigation

Automatons

Automatons is a React/JavaScript side effect management library based on finite state machines that enables you to keep your logic clear by describing it formally in terms of automata theory.

Contents

  1. The Why
  2. Installation
  3. Getting Started
  4. API Documentation
  5. Contributing

The Why

View layer logic often tends to get messy, especially when dealing with asynchronous external events from network or complex animations and user input.

State machines help to untangle the spaghetti logic as it is described formally as a series of states, transitions and side effects.

Installation

Getting Started

A state machine is an abstract mechanism that is capable of remembering it's current state and changing it according to a pre-determined set of rules.

Automatons library provides a function to construct such state machines:

import {automaton} from "automatons";

const stateMachine = automaton([
	/* List of transition rules go here */
])

Basic Usage

(See 01: Basic Usage on codesandbox.io)

A state machine can be defined by three components:

  • a list of all possible states;
  • a list of rules to change the remembered state;
  • an initial state.

All Automatons state machines start in a special INITIAL state, reference to which is provided by the library:

import {INITIAL} from "automatons";

Transitions is Automatons library are triggered by external events called signals and are described by transition function:

import {automaton, transition, INITIAL} from "automatons";

const stateMachine = automaton([
	/**
	* Transitioning from INITIAL state to "clicked" on any signal
	*/
	transition(INITIAL, () => "clicked"),
	/**
	* Transitioning from "clicked" state back to INITIAL on "reset" signal
	*/
	transition("clicked", "reset", INITIAL),
]);

// Triggering the transition
stateMachine.transition("");
console.log(stateMachine.state); // "clicked"

// Triggering it again!
stateMachine.transition("reset");
console.log(stateMachine.state); // INITIAL

React Binding

(See 02: React Binding on codesandbox.io)

Automatons library provides bindings to React to make possible the usage of state machines in view layer logic.

You can add a state machine to any React component by applying a @withAutomaton decorator:

import {withAutomaton} from "automatons";

@withAutomaton
class Button extends React.Component {
	transitions = [
		/* List of state machine transitions */
	]
}

Automatons supports automatic state mapping and automatic component updates with the help of mapToState parameter:

import {withAutomaton} from "automatons";

@withAutomaton({
	mapToState: "phase",
})
class Button extends React.Component {
	/**
	* Now this.state.phase always refers to the current automaton state
	*/
}

It is also possible to automatically bind React event callbacks to automaton signals with the help of asSignal:

import {withAutomaton, asSignal} from "automatons";

@withAutomaton
class Button extends React.Component {
	render() {
		return (
			<button onClick={asSignal(this, "click")}>
				Click me!
			</button>
		);
	}
}

Timers

(See 03: State Mapping & Timers on codesandbox.io)

One of the most prominent features of Automatons is the ability to perform transitions automatically after a timeout:

import {automaton, timer, INITIAL} from "automatons";

const stateMachine = automaton([
	/**
	* Transitioning from INITIAL state to "ready" in 100 milliseconds
	*/
	timer(INITIAL, 100, "ready"),
	/**
	* Transitioning from "ready" state to "sleeping" in 4 seconds
	*/
	timer("ready", 4000, "sleeping"),
]);

Advanced Side Effects

(See 04: Advanced Side Effects on codesandbox.io)

It is possible to perform a side effect that does not trigger any state change:

import {automaton, transition, sideEffect, INITIAL} from "automatons";

const stateMachine = automaton([
	/**
	* Side effect will be performed if in INITIAL state and "click" signal
	* is dispatched
	*/
	sideEffect(INITIAL, "click", () => {
		alert("Clicked!");
	}),
	/**
	* And that side effect does not stop the transition from INITIAL to
	* "clicked" on the same signal from happening.
	*/
	transition(INITIAL, "click", "clicked"),
]);

API Documentation

For further information please refer to API Documentation.

Contributing

When contributing to Automatons, please open an issue first.

Please note the code of conduct, it is desired to follow it in all your interactions with the project.

Reporting Bugs

When reporting a bug, please provide a minimal case of reproduction, which can be:

  • a test that is broken but should not be,
  • a Codesandbox project in which the bug occurs.

Pull Request Process

When sending a pull request, please do not forget the following:

  • resolve all conflicts with master branch,
  • update the README.md and/or the documentation in comments according to your changes,
  • ensure the documentation build is up-to-date in docs folder,
  • ensure the new functionality is covered by tests, and all tests pass.

About

A JavaScript side effect management library based on finite state machines

Resources

Code of conduct

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published