Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
becousae committed Dec 14, 2017
1 parent ceee827 commit 4167620
Show file tree
Hide file tree
Showing 10 changed files with 6,726 additions and 0 deletions.
1 change: 1 addition & 0 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
lib/
116 changes: 116 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,118 @@
# fsm-hoc
Higher Order Component to introduce Finite State Machine to React Components

## Installation
```sh
npm install fsm-hoc --save
```

## Usage

This module provides a function to wrap your components in a finite state machine.

### Type arguments

#### Props
The Props interface of your component you want to wrap

#### State
The State interface of your component you want to wrap

#### Status
An enum that lists the statuses your component can be in

#### Action
An enum that lists the actions that can be triggered to change a status

### Arguments

#### StatusMachine

This is an object that describes which actions can be triggered on which statuses,
and the status they go into.

```typescript
const statusMachine = {
[Status.Idle]: {
[Action.Submit]: Status.Loading,
},
[Status.Loading]: {
[Action.Error]: Status.Error,
[Action.Success]: Status.Success,
},
[Status.Error]: {
[Action.Submit]: Status.Loading,
},
};
```

#### Commands

Commands are side-effects that are triggered when a component changes to a new status.

```typescript
const commands = {
[Status.Error]: (component: React.Component<Props, State>) => {
// Side effects
component.setState({ errorMsg: 'Wrong parameters.' });
},
};
```

#### Initial Status

The status to start in.

### Complete example
```typescript
import fsm, { InjectedProps } from 'fsm-hoc';

enum Status {
Idle,
Loading,
Error,
Success
}

enum Action {
Submit, Error, Success
}

const statusMachine = {
[Status.Idle]: {
[Action.Submit]: Status.Loading,
},
[Status.Loading]: {
[Action.Error]: Status.Error,
[Action.Success]: Status.Success,
},
[Status.Error]: {
[Action.Submit]: Status.Loading,
},
};

const commands = {
[Status.Error]: (component: React.Component<Props, State>) => {
// Side effects
component.setState({ errorMsg: 'Wrong parameters.' });
},
};

class Form extends React.Component<Props & InjectedProps<Status, Action>, State> {

...

render() {
return (
...
<input type="button" disabled={this.props.status !== Status.Loading}>Submit</input>
...
);
}

...

}

export default fsm<Props, State, Status, Action>(statusMachine, commands, Status.Idle)(Form);
```
16 changes: 16 additions & 0 deletions dist/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import * as React from 'react';
export interface Action<T> {
type: T;
}
export interface InjectedProps<S, A> {
transition: (component: React.Component, action: Action<A>) => void;
status: S;
}
export default function fsm<Props, State, Status, ActionType>(statusMachine: any, commands: any, initialStatus: Status): (Component: any) => {
new (props: Props): {
transition(component: any, action: Action<ActionType>): void;
command(nextStatus: Status, action: Action<ActionType>): void;
render(): any;
};
displayName: string;
};
Loading

0 comments on commit 4167620

Please sign in to comment.