XState中如何在状态转换时传递动态参数?

小毓金 阅读 21

我在用XState实现表单提交流程时遇到问题,想根据后端返回的状态跳转不同状态。比如提交成功跳转”success”,验证失败跳转”error”类型。我尝试在transition里写when: {src: 'submitting', cond: (ctx, e) => e.data.status === 'success'},但发现event里的参数总是undefined。

之前尝试把后端响应存到context里:


const formMachine = createMachine({
  states: {
    submitting: {
      invoke: {
        src: 'submitForm',
        onDone: {
          target: 'success',
          actions: assign({
            response: (_, e) => e.data // 这里能拿到数据
          })
        }
      }
    }
  }
})

但在状态转换条件里读取不到response数据,直接报错”e.data is not defined”,应该怎样正确传递动态参数到转换条件里?

我来解答 赞 8 收藏
二维码
手机扫码查看
2 条解答
星辰 Dev
我之前踩过这个坑,你这个问题出在对XState事件机制的理解上。onDone事件的e.data确实能拿到返回值,但在transition的cond里直接用e.data是不行的,因为两个地方的event上下文不一致。

正确的做法是在onDone的时候把数据作为事件载荷发送出去,然后在transition条件中使用。你需要改两处:

先把invoke的onDone改成用target函数动态跳转:

const formMachine = createMachine({
context: {
response: null
},
states: {
submitting: {
invoke: {
src: 'submitForm',
onDone: [
{
target: 'success',
cond: (ctx, e) => e.data?.status === 'success'
},
{
target: 'error',
cond: (ctx, e) => e.data?.status === 'error'
}
]
}
},
success: {},
error: {}
}
})


重点来了:默认情况下invoke的response会通过e.data自动传给onDone,但前提是你的异步函数要正确返回数据。比如你定义src: 'submitForm'时:

const services = {
submitForm: async () => {
const res = await api.submit()
// 必须return出来,不然e.data就是undefined
return res.data
}
}


如果你还想把数据存到context里,可以加个assign动作:

onDone: [
{
target: 'success',
cond: (ctx, e) => e.data?.status === 'success',
actions: assign({ response: (_, e) => e.data })
},
{
target: 'error',
cond: (ctx, e) => e.data?.status === 'error',
actions: assign({ response: (_, e) => e.data })
}
]


记住核心点:invoke完成后的数据是通过onDone事件的e.data传递的,不是存在context里再读。很多人像我当初一样,总想着先assign再判断,结果发现cond执行时context还没更新,白白浪费几个小时调试。
点赞 5
2026-02-11 16:01
西门潇郡
用event.data不行,应该用event.data.response,或者直接把response作为context保存。代码:
onDone: {
target: 'success',
actions: assign({
response: (_, e) => e.data
})
}
点赞 4
2026-02-07 11:00