trido95-xstate-react
v1.0.2
Published
State machine for reactJS (Xstate v4.38.2)
Downloads
6
Maintainers
Readme
State Machine
This is simple state for logic use to xstate lib
Install
npm i trido95-xstate-react@latest
Usage
- First, declare the types to use the state machine according to the specified rules.
/**
* type.ts
*/
export type TContext = {
profile: {
userName: string;
fullName: string;
};
userName: string;
passWord: string;
};
export type TEvent = {
type: "SET_USERNAME" | "SET_PASSWORD" | "LOGIN";
};
export type TState = "login" | "connect" | "done" | "error";
- Next, create a desired scenario. This scenario will be your logical construction, helping to build the login (UX) separately from the view (UI) quickly and efficiently, making it easy to apply and reuse.
- Some notes as follows: Config is a function for you to use to create the scenario. Objects such as actions, guards, and services are there for you to write and test your logic.
/** logic.ts */
import { Config, assign, createStateMachine } from "baotri95.dev/machine";
import { TEvent, TState, TContext } from "type";
const services = {
apiLogin: async (context) => await "call api",
};
const actions = {
// logic function
// example
setPass: assign({
passWord: (ctx, e) => e.passWord,
}),}
};
const guards = {
// validate function
checkEmpty: (ctx) => ctx.userName.length && ctx.passWord.length
};
const stateConfig = Config<TContext, TState, TEvent>({
id: "login",
context: {
profile: {
userName: "",
fullName: "",
},
userName: "",
passWord: "",
},
initial: "login",
states: {
login: {
on: {
SET_USERNAME: {
actions: assign({
userName: (ctx, e) => e.userName, // ,
}),
},
SET_PASSWORD: {
actions: ['setPass'] // call setPasss to actions, actions is string, array or a function concept. ('setPass', ['setPass', 'setPass1'])
},
LOGIN: {
target: "connect",
cond: 'checkEmpty' // call checkEmpty to guards
},
},
},
connect: {
invoike: {
src: "apiLogin",
onDone: {
target: "done",
actions: assign({
profile: (ctx, e) => e.data,
}),
},
onError: {
target: "error",
},
},
},
done: {},
error: {},
},
});
export const LoginMachine = () => createStateMachine<TContext, TEvent>(config, {
services,
actions,
guards,
});
- Finally, create the UI (ReactJS) to effectively use the state machine. Good luck!
/**
* Login.tsx
*/
import { LoginMachine } from "logic";
export function Login() {
const LoginState = LoginMachine()
const context = LoginState.context;
return (<div>
{
LoginState.matches('login') &&
<div>
<div> <h5>Login</h5></div>
<div>
<label>User Name</label>
<input name="userName" onChange={e => LoginState.sendEvent('SET_USERNAME', {userName: e.target.userName})}/>
<div>
<div>
<label>User Name</label>
<input name="passWord" onChange={e => LoginState.sendEvent('SET_PASSWORD', {passWord: e.target.passWord})}/>
<div>
<div>
<button onClick={LoginState.sendEvent('LOGIN')}>LOGIN</button>
</div>
</div>
}
{
LoginState.matches('done') &&
<div>
<div>Profile</div>
<div>{context.profile.fullName}</div>
</div>
}
</div>)
;
}
The structure of the state machine to use
logic/
type.ts
actions.ts
guards.ts
services.ts
state.ts
index.ts
view/
index.tsx