Skip to content

🕵️‍♂️ Delightful state management for the frustrated React developer. Minimal boilerplate. Small footprint. Elegant API.

Notifications You must be signed in to change notification settings

pringshia/machinate

Repository files navigation

🕵️‍♂️ machinate

npm build

⚠️ Not yet ready for production use.


machinate (mack·in·eight) verb:

  • Practical, simple, and hassle-free state management.

  • A cutesy reverse portmanteau of "state machine".

  • To engage in plots and intrigues; scheme. (This is what your app does if you're not managing state properly, we'll help put an end to that.)


🏁 Goals:

  • 🚀 Instantly launch your app in any given state.
  • 🤓 Heavy emphasis on developer experience. Your time and sanity are respected.
  • 🚼 Baked in best practices. Guardrails for guidance.
  • 🍞 Dead simple. Plain javascript objects. Minimal boilerplate.
  • 🛠 High quality tooling.

Install

yarn add machinate

Use

Every app has states. 1) Define them. 2) Implement them. 3) Connect them.

1. define your app's states

// object where keys are a domain, values are the states of that domain.

const scheme = {
  Auth: ["LoggedIn", "LoggedOut", "Unknown"]
};

2. implement the states

import { Machinate, States } from "machinate";

const initialState = { Auth: "LoggedOut" };

const App = (
    <Machinate
        scheme={scheme}
        initial={initialState}>

        <States of="Auth"
            LoggedIn={...}
            LoggedOut={...}
            Unknown={...}
        />
    </Machinate>
);

ReactDOM.render(<App />, document.body)

💡 Tip! If you forget to implement a state, machinate will warn you:

<States of="Auth"
    LoggedIn={...}
    LoggedOut={...}
    // 'Unknown' prop left out intentionally
>

web console:

Warning: Failed prop type: The prop `Unknown` is marked as required in `Auth[Domain]`, but its value is `undefined`.

3. connecting states

Each state prop receives an object with the following parameters:

  1. data: the data if any, associated with the state
  2. transition(stateName, optionalData): move the machine to stateName and set the data associated with the state to data
  3. go(stateName, optionalData): same as transition(), but wrapped in a function to delay execution; essentially a convenient helper for transitioning on callbacks
  4. update(stateName, updateFn): same as transition(), except the second parameter is a function that transforms the current data to new data

Here we use the go() function:

<States of="Auth"
    LoggedIn={({data}) => <h1>Hi {data.user}</h1>}
    LoggedOut={({ go }) => (
        <button
            onClick={ go("Auth.LoggedIn", {user: "bob"}) }
            value="Login"
        />
    )}
    Unknown={() => null)}
/>

Note: "Auth.LoggedIn" is shorthand notation, referring to the LoggedIn state of the Auth domain.


🔀 Syntactic Shortcuts

The following are all equivalent:

const scheme = {
  Auth: ["LoggedIn", "LoggedOut"]
};

const scheme = {
  Auth: {
    states: ["LoggedIn", "LoggedOut"],
    deps: []
  }
};
const initialState = {
  Auth: "LoggedOut"
};

const initialState = {
  Auth: {
    state: "LoggedOut",
    data: null
  }
};

About

🕵️‍♂️ Delightful state management for the frustrated React developer. Minimal boilerplate. Small footprint. Elegant API.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published