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.)
- 🚀 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.
yarn add machinate
Every app has states. 1) Define them. 2) Implement them. 3) Connect them.
// object where keys are a domain, values are the states of that domain.
const scheme = {
Auth: ["LoggedIn", "LoggedOut", "Unknown"]
};
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`.
Each state prop receives an object with the following parameters:
data
: the data if any, associated with the statetransition(stateName, optionalData)
: move the machine tostateName
and set the data associated with the state todata
go(stateName, optionalData)
: same astransition()
, but wrapped in a function to delay execution; essentially a convenient helper for transitioning on callbacksupdate(stateName, updateFn)
: same astransition()
, 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.
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
}
};