XState
使用xstate提供的 Machine、useMachine
App.js
import React from 'react';
import logo from './logo.svg';
import './App.css';
import { Machine } from 'xstate';
import { useMachine } from '@xstate/react';
import { RedLight, GreenLight, YellowLight } from './Light'
const LIGHT_STATES = {
RED: 'RED',
YELLOW: 'YELLOW',
GREEN: 'GREEN',
}
const LIGHT_CLICK = {
CLICK: 'CLICK'
}
const lightMachine = Machine({
initial: LIGHT_STATES.RED,
states: {
[LIGHT_STATES.RED]: {
on: {
[LIGHT_CLICK.CLICK]: LIGHT_STATES.YELLOW,
}
},
[LIGHT_STATES.YELLOW]: {
on: {
[LIGHT_CLICK.CLICK]: LIGHT_STATES.GREEN,
}
},
[LIGHT_STATES.GREEN]: {
[LIGHT_CLICK.CLICK]: LIGHT_STATES.RED
}
}
})
function App() {
const [state, send] = useMachine(lightMachine)
return (
<div className="App">
{state.matches(LIGHT_STATES.RED) && <RedLight/>}
{state.matches(LIGHT_STATES.YELLOW) && <YellowLight/>}
{state.matches(LIGHT_STATES.GREEN) && <GreenLight/>}
<button onClick={() => { send(LIGHT_CLICK.CLICK)}}>
click me
</button>
</div>
);
}
export default App;
App.css
.App {
text-align: center;
}
.light {
display: inline-block;
width: 30px;
height: 30px;
border-radius: 50%;
margin-right: 15px;
}
.red {
background-color: red;
}
.yellow {
background-color: yellow;
}
.green {
background-color: green;
}
Light.js
import React from 'react'
export function RedLight() {
return <span className="light red"></span>
}
export function YellowLight() {
return <span className="light yellow"></span>
}
export function GreenLight() {
return <span className="light green"></span>
}