I just found a finite state module called Robot. it's very lightweight and simple. I got one case I couldn't solve, which is to create a dynamic request for API inside Robot. I tried this
robot.js
const context = () => ({
data: [],
});
export const authRobot = (request) =>
createMachine(
{
ready: state(transition(CLICK, 'loading')),
loading: invoke(
request,
transition(
'done',
'success',
reduce((ctx, evt) => ({ ...ctx, data: evt }))
),
transition(
'error',
'error',
reduce((ctx, ev) => ({ ...ctx, error: ev }))
)
),
success: state(immediate('ready')),
error: state(immediate('ready')),
},
context
);
and I use it in my react component like this
// ...
export default function Login() {
const [current, send] = useMachine(authRobot(UserAPI.getData));
const { data } = current.context;
function handleSubmit(e) {
e.preventDefault();
send(CLICK);
}
useEffect(() => {
console.log(data);
console.log(current);
console.log(current.name);
}, [data]);
// ...
the problem happened when I click the button, my web console logs many data. it seems the event called multiple times. what can I do here?
I think the problem here is that
useMachine()
will trigger a rerender when passed a different machine. Since you are creating a new machine inside your render function useMachine sees this as a different machine every time.I'd create your machine outside of this closure.