You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在XState 5的onDone中正确使用Guard守卫?

XState 5中onDone的Guard配置问题解决

问题场景

我在编写XState 5状态机时遇到Guard不生效的问题:在checkingSession状态的invoke的onDone数组中,通过cond判断event.output.isAuthenticated的值,期望true时跳转至authenticated状态,false时跳转至notAuthenticated状态。但实际运行时,当event.output.isAuthenticated为false时,依然执行了authenticated状态的跳转和对应actions。

代码示例

checkingSession: {
        entry: () => console.log('Entered Checking status state'),
        invoke: {
            src: checkSession,
            input: ({context}) => ({
                auth0Client: context.auth0Client
            }),
            onDone: [
                {
                    target: 'authenticated',
                    cond: (_, event) => {
                        console.log(`This user is authenticated ${event.output.isAuthenticated}`);
                        return event.output?.isAuthenticated
                    },
                    actions: ({context, event}) => {
                        console.log("This does work "+event.output.isAuthenticated)
                        context.user = event.output.user;
                        context.isAuthenticated = event.output.isAuthenticated;
                    }
                },
                {
                    target: 'notAuthenticated'
                }
            ],
            onError: {
                target: 'error',
                actions: assign({
                    error: (_, event) => event.error?.message || 'Failed to check session'
                })
            }
        }
},
notAuthenticated: {
        entry: () => console.log('Entered notAuthenticated state'),
        on: {
            LOGIN: 'authenticating'
        }
},
authenticated: {
        entry: () => console.log('Entered authenticated state'),
        on: {
            LOGOUT: 'loggingOut',
            REFRESH: 'refreshing'
        }
},

运行日志

Entered Checking status state
index.js:23 Checking session...
index.js:85 This does work false
index.js:130 Entered authenticated state

问题原因与修复步骤

1. 确保Guard返回严格布尔值

你的Guard函数return event.output?.isAuthenticated可能因为isAuthenticated的类型问题(比如是字符串"false"、0等假值但非布尔false),导致返回值不符合预期。即使日志显示isAuthenticated为false,也可能存在类型隐式转换的问题。

修复:使用严格相等判断明确布尔值

cond: (_, event) => {
    console.log(`This user is authenticated ${event.output.isAuthenticated}`);
    // 严格匹配布尔类型的true
    return event.output?.isAuthenticated === true;
}

2. 修正Context修改方式

你在action中直接修改context.user和context.isAuthenticated的写法不符合XState规范,会导致状态上下文不可预测,甚至间接影响Guard的判断逻辑。XState要求必须通过assign动作修改上下文:

修复:替换为assign动作

actions: assign({
    user: (_, event) => event.output.user,
    isAuthenticated: (_, event) => event.output.isAuthenticated
})

3. 为默认分支添加明确Guard(可选但推荐)

虽然XState会按顺序匹配onDone数组中的条目(第一个不匹配则执行第二个),但为了代码可读性和逻辑严谨性,建议给notAuthenticated分支添加明确的Guard:

{
    target: 'notAuthenticated',
    cond: (_, event) => event.output?.isAuthenticated !== true
}

修正后的完整代码片段

checkingSession: {
        entry: () => console.log('Entered Checking status state'),
        invoke: {
            src: checkSession,
            input: ({context}) => ({
                auth0Client: context.auth0Client
            }),
            onDone: [
                {
                    target: 'authenticated',
                    cond: (_, event) => {
                        console.log(`This user is authenticated ${event.output.isAuthenticated}`);
                        return event.output?.isAuthenticated === true;
                    },
                    actions: assign({
                        user: (_, event) => event.output.user,
                        isAuthenticated: (_, event) => event.output.isAuthenticated
                    })
                },
                {
                    target: 'notAuthenticated',
                    cond: (_, event) => event.output?.isAuthenticated !== true
                }
            ],
            onError: {
                target: 'error',
                actions: assign({
                    error: (_, event) => event.error?.message || 'Failed to check session'
                })
            }
        }
},
notAuthenticated: {
        entry: () => console.log('Entered notAuthenticated state'),
        on: {
            LOGIN: 'authenticating'
        }
},
authenticated: {
        entry: () => console.log('Entered authenticated state'),
        on: {
            LOGOUT: 'loggingOut',
            REFRESH: 'refreshing'
        }
},

内容的提问来源于stack exchange,提问作者Jackie

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 02:09:50