Package Exports
- use-tiny-state-machine
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (use-tiny-state-machine) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
useTinyStateMachine
A tiny (~700 bytes) react hook to help you write finite state machines
Read the documentation for more information
Install
Import
yarn add use-tiny-state-machine
Examples
Manual traffic lights
import useTinyStateMachine from 'use-tiny-state-machine';
const stateChart = {
id: 'traffixLight',
initial: 'green',
states: {
green: { on: { NEXT: 'red' } },
orange: { on: { NEXT: 'green' } },
red: { on: { NEXT: 'orange' } },
},
};
export default function ManualTrafficLights() {
const { cata, state, dispatch } = useTinyStateMachine(stateChart);
return (
<Fragment>
<div
className="trafficLight"
style={{
backgroundColor: cata({
green: '#51e980',
red: '#e74c3c',
orange: '#ffa500',
}),
}}
>
The light is {state}
</div>
<button onClick={() => dispatch('NEXT')}>Next light</button>
</Fragment>
);
};
Automated traffic lights with onEntry action
onEntry
is called every time you enter a given state. onEntry
is called with the current state machine instance.
import useTinyStateMachine from 'use-tiny-state-machine';
const stateChart = {
id: "traffixLight",
initial: "green",
states: {
green: {
onEntry: waitForNextLight,
on: {
NEXT: "red"
}
},
orange: {
onEntry: waitForNextLight,
on: {
NEXT: "green"
}
},
red: {
onEntry: waitForNextLight,
on: {
NEXT: "orange"
}
}
}
};
function waitForNextLight({ dispatch }) {
const timer = setTimeout(() => dispatch('NEXT'), 1000);
return () => clearTimeout(timer);
}
function TrafficLights() {
const { cata, state, dispatch } = useTinyStateMachine(stateChart);
return (
<Fragment>
<div
style={{
width: "30px",
height: "30px",
backgroundColor: cata({
green: "#51e980",
red: "#e74c3c",
orange: "#ffa500"
})
}}
>
The light is {state}
</div>
<button onClick={() => dispatch("NEXT")}>Force next light</button>
</Fragment>
);
}
Fetching data
You can use context to store any data associated with a state.
const stateChart = {
id: 'userData',
initial: 'idle',
context: {
data: null,
error: null,
},
states: {
idle: {
on: {
FETCH: {
target: 'pending',
action: ({ dispatch }, userId) => {
fetchUser(userId)
.then(user => dispatch('SUCCESS', user))
.catch(error => dispatch('FAILURE', error));
},
},
},
},
pending: {
on: {
SUCCESS: {
target: 'success',
beforeStateChange: ({ updateContext }, data) => updateContext(c => ({ ...c, data })),
},
FAILURE: {
target: 'failure',
beforeStateChange: ({ updateContext }, error) => updateContext(c => ({ ...c, error })),
},
},
},
},
};
const UserData = () => {
const { context, dispatch, cata } = useTinyStateMachine(stateChart);
return (
<div>
{cata({
idle: () => (
<button onClick={() => dispatch('FETCH')}>
Fetch user data
</button>
),
pending: () => <Spinner />,
success: () => `Hi ${context.data.name}`,
failure: () => `Error: ${context.error.message}`,
})}
</div>
);
};