How to give dynamic request to robot?

113 Views Asked by At

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?

1

There are 1 best solutions below

2
On

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.