react-finite-state-machine
v1.1.0
Published
React finite state machine
Downloads
7
Readme
React Finite State Machine
React component that implements the logic of the finite-state machine. Allows describing the component's state and the logic behind interstate transitions, transferring useful data between stages.
Prop Types
FSM Component Props
| Property | Type | Required? | Description | |:---|:---|:---:|:---| | meta | Meta | ✓ | Metdata. Description of stages. | | onFinish | OnFinish | | Hook activated after the transition to the final stage, finish() method call in the component. | | beforeTransition | BeforeTransition | | Hook activated before the transition to the preset stage. It's possible to interrupt the transition to the preset stage by returning false or Promise. | | afterTransition | AfterTransition | | Hook activated after the transition to the preset stage. | | Layout | React.ReactType | | General layout for all nodes of a finite state machine that receives information about the current step and children for rendering | | commonProps | any | | General parameters that will be sent to each node component of a finite state machine |
type StageName = string | number;
/**
* History of interstage transitions
*/
interface IHistory {
/** Number of records in history */
recordsCount: number;
/** Link to the first record's object in history */
first: IStage | null;
/** Link to the last record's object in history */
last: IStage | null;
/**
* Method of adding a new record to history
* @param {StageName} stageName Stage name
* @param {any} payload
* @returns {void}
*/
add: (stageName: StageName, payload: any) => void;
}
type Meta<Stage extends StageName = string> = {
/** List of stages and corresponding components ('name-component' pair) */
stages: {
[name in Stage]: React.ElementType<StageComponentProps>;
};
/** Initial stage */
initialStage: Stage;
/** Final stage */
finalStage: Stage;
};
type OnFinish: (transitionsHistory: IHistory) => void;
type BeforeTransition = (currentStage: StageName, nextStage: StageName, payload?: any) => boolean;
type AfterTransition = (currentStage: StageName, prevStage: StageName, payload?: any) => void;
type CommonProps = any;
type Layout = React.ElementType<LayoutComponentProps>;
Stage Component Props
| Property | Type | Description | |:---|:---|:---| | transition | Transition | Method of transition to the present stage. Can accept useful data for transferring to the next stage. | | toPrevious | ToPrevious | Method of returning to the preceding stage. Can accept useful data for transferring to the previous stage. | | finish | () => void | Calls onFinish hook. | | payload | IncomingPayload | Data transferred from the preceding stage. | | commonProps | any | General parameters that will be sent to each node component of a finite state machine |
type IncomingPayload = {} | void;
type OutGoingPayload = {} | void;
type ToPrevPayload = OutGoingPayload;
type Transition = (stageName: StageName, payload?: OutGoingPayload) => Promise<void>;
type ToPrevious = (payload?: ToPrevPayload) => Promise<void>;
type CommonProps = any;
Examples
import React from 'react';
import ReactDOM from 'react-dom';
import {FSM} from 'react-fsm';
const commonProps = {
key: 'value'
};
const Layout = ({children, currentStage, currentStagePayload}) => (
<div>
{children}
</div>
);
const Stage = {
Stage1: 'Stage1',
Stage2: 'Stage2',
Stage3: 'Stage3'
};
const formsMeta = {
stages: {
[Stage.Stage1]: ({transition}) => (
<div onClick={() => transition(Stage.Stage2)}>
Stage 1
</div>
),
[Stage.Stage2]: ({transition}) => (
<div onClick={() => transition(Stage.Stage3)}>
Stage 2
</div>
),
[Stage.Stage3]: ({finish}) => (
<div onClick={() => finish()}>
Stage 3
</div>
)
},
initialStage: Stage.Stage1,
finalStage: Stage.Stage3
};
const Form = () => (
<FSM
meta={formsMeta}
afterTransition={(currentStage, prevStage, payload) => {
console.log(
`We've made a transition to the stage ${currentStage}`,
`From stage ${prevStage}`,
`Received payload: ${payload}`
);
}}
beforeTransition={(currentStage, nextStage, payload) => {
console.log(
`Try to make a transition to the stage ${nextStage}`,
`From stage ${prevStage}`,
`With payload: ${payload}`
);
return !!payload.hasCats;
}}
onFinish={(transitionsHistory) => {
console.log(`Finish. History: ${transitionsHistory}`);
}}
commonProps={commonProps}
Layout={Layout}
/>
);
ReactDOM.render(
<Form />,
document.getElementById('example')
);