1

我有 xstate 反应脚本,用户填写表格,然后按提交。提交时,xstate 收到了一个 send("VALIDATE", {formData}) ,它通过验证表单的服务运行。成功后,脚本将转换到目标:“成功”,我需要最终的“成功”状态来调用实际上保存脚本的外部函数。

我可以将数据获取到验证器函数中,但是在onDone之后,后续的成功状态似乎看不到数据。

如何将数据从验证事件连接到成功事件?

 id: 'validator',
        initial: 'populating',
        context: {},
        states: {
        populating: {
            on: {
            VALIDATE: 'validating'
            }
        },
        validating: {
            invoke: {
            src: (context, data) => doValidate(data),
            onDone: {
                target: 'success',
                actions: assign({ data: "hello world"})
            },
            onError: 'failure'
            }
        },
        success: {
            invoke: {
                // I do see the hello world here, but what I want is the 'data' from the  doValidate(data)
                src: (ctx)=>{console.log("invoked success, what can I see here: ", ctx)}
            } 
        },

我通过以下方式触发验证:send("VALIDATE", formData)

4

2 回答 2

2

如果我理解正确,您希望第一个服务的事件onDone可用于第二个服务?最简单的方法是将数据放在另一个上并context在另一个上访问它,state/service然后再将其删除。

或者,您可以send在第一次服务完成后将您的机器建模为自定义事件。

import { createMachine, assign, send, interpret } from "xstate";

const machine = createMachine({
  preserveActionOrder: true, //make sure actions are executed in order
  id: "validator",
  initial: "populating",
  context: {},
  states: {
    populating: {
      on: {
        VALIDATE: "validating"
      }
    },
    validating: {
      on: {
        // Listen to the event that fires when the first service is done
        FIRST_SERVICE_DONE: {
          target: "success"
        }
      },
      invoke: {
        src: (context, data) => Promise.resolve({ prop: "first service" }),
        onDone: {
          // target: 'success',
          actions: [
            assign({ data: "hello world" }),
            //instead of using target:'success' send a custom 
            //event that has access to the data from the service
            send((context, event) => {
              //event here has  event.data.prop === 'first service'
              console.log("send evt ", event);
              return {
                type: "FIRST_SERVICE_DONE",
                prop: event.data.prop
              };
            })
          ]
        },
        onError: "failure"
      }
    },
    success: {
      invoke: {
        src: (_ctx, evt) => {
          console.log("evt ", evt.prop);  //first service
        }
      }
    },
    failure: {}
  }
});

const service = interpret(machine);

service.start();

service.send({ type: "VALIDATE" });

代码沙盒

于 2021-08-14T11:20:11.000 回答
1

在 Xstate 中,上下文是扩展状态,因此将上下文用作“机器内存”似乎不是一个好习惯。使用扩展状态,这样您就不会拥有无限数量的状态。

如果您需要保留由事件发送到调用 Promise 的状态的信息,您可以将该信息添加到响应中。例如:

export const myMachineServices = {
  myRequest: (context, event) =>
    new Promise(resolve => {
      setTimeout(() => {
        resolve({
          payload: 'some data',
        })
      }, 1000)
    }).then(res => ({
      ...res,
      event.data
    }))
    .catch(err => ({
      ...err,
      event.data
    })),
}

于 2021-12-21T18:20:15.157 回答