@metreeca/tile
    Preparing search index...

    Headless component state.

    Turns an immutable state object into the state of a component: useModel holds it for the lifetime of the component and renders again after every transition that changes something, so behaviour defined once as a state object drives any component that adopts it.

    Usage

    Declare what the component is responsible for as a state interface, with read-only data and transition methods:

    interface Counter {

    readonly value: number;

    up(): this;
    reset(): this;

    }

    Give it a factory, which may share the interface name, as types and values live in separate namespaces:

    import { createState } from "@metreeca/core/state";

    function Counter() {
    return createState<Counter>({

    value: 0,

    up() { return { value: this.value + 1 }; },
    reset() { return { value: 0 }; }

    });
    }

    Where a component already answers to Counter, name the factory createCounter: a module cannot import both.

    Then read data and transitions off the model: a transition is bound to the state it was read from, so a zero-argument one goes straight to a handler, and any of them may be stored and passed on:

    export function CounterButton() {

    const { value, up, reset } = useModel(Counter);

    return <>
    <button onClick={up}>+</button>
    <button onClick={reset}>~</button>
    <output>{value}</output>
    </>;

    }

    Transitions do not accumulate

    Every transition starts from the state of the render that read it, so taking one twice lands where once does:

    const twice = () => {
    up(); // value + 1
    up(); // value + 1 again, not value + 2
    };

    A transition also notifies asynchronously, so data read alongside keeps its earlier value until the next render:

    const report = () => {
    up();
    console.log(value); // still the value before the transition
    };

    Unmounting

    A model needs no cleanup when the component goes away, nothing outliving it to detach from: the model, its observers and the setter they notify become unreachable together. This holds as long as models stay local to the component, so a model is never parked in a module-level cache or handed to an external store. A transition taken just before unmounting notifies after it, which the state module absorbs without effect.

    useModel

    Adopts a state object as the state of a component.