1.1.0 • Published 5 years ago

react-finite-state-machine v1.1.0

Weekly downloads
9
License
MIT
Repository
github
Last release
5 years ago

React Finite State Machine

Documentation in Russian

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

PropertyTypeRequired?Description
metaMetaMetdata. Description of stages.
onFinishOnFinishHook activated after the transition to the final stage, finish() method call in the component.
beforeTransitionBeforeTransitionHook activated before the transition to the preset stage. It's possible to interrupt the transition to the preset stage by returning false or Promise.
afterTransitionAfterTransitionHook activated after the transition to the preset stage.
LayoutReact.ReactTypeGeneral layout for all nodes of a finite state machine that receives information about the current step and children for rendering
commonPropsanyGeneral 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

PropertyTypeDescription
transitionTransitionMethod of transition to the present stage. Can accept useful data for transferring to the next stage.
toPreviousToPreviousMethod of returning to the preceding stage. Can accept useful data for transferring to the previous stage.
finish() => voidCalls onFinish hook.
payloadIncomingPayloadData transferred from the preceding stage.
commonPropsanyGeneral 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')
);