我使用xstate和react来实现基本的登录功能。代码是这里,我面临的问题是,在事件AUTHENTICATING上,它是为了调用服务authenticateUser,而不是调用服务authenticateUser。控制台中没有可见的错误。组件看起来就像
import { useMachine } from "@xstate/react";
import { createMachine, assign } from "xstate";
import "./App.css";
const authenticateUserNew = async (c, e) => {
console.log("service invoked");
return new Promise((resolve, reject) => {
setTimeout(() => {
if (Math.random() > 0.5) {
resolve();
} else {
reject();
}
}, 1000);
});
};
const loginMachine = createMachine(
{
id: "login-machine",
initial: "unauthenticated",
context: {
isAuthenticated: false,
},
states: {
unauthenticated: {
on: {
AUTHENTICATING: {
invoke: {
id: "authenticateUser",
src: (c, e) => authenticateUserNew(c, e),
onDone: {
target: "authenticated",
actions: assign({ isAuthenticated: (context, event) => true }),
},
onError: {},
},
},
},
},
authenticated: {
on: {
LOGOUT: {
target: "unauthenticated",
},
},
},
},
},
{
services: {
authenticateUser: () => {
console.log("service invoked");
return new Promise((resolve, reject) => {
setTimeout(() => {
if (Math.random() > 0.5) {
resolve();
} else {
reject();
}
}, 1000);
});
},
},
}
);
function App() {
const [current, send] = useMachine(loginMachine);
return (
<div className="App">
<h2>{current.value}</h2>
<br />
<h3>
isAuthenticated: {current.context.isAuthenticated ? "True" : "False"}
</h3>
<br />
<button onClick={() => send("AUTHENTICATING")}>AUTHENTICATE</button>
<br />
<button onClick={() => send("LOGOUT")}>LOGOUT</button>
</div>
);
}
export default App;我已经尝试过两种方法,在这两种方法中,我都可以将函数外部化并使用它,或者在状态机的service部分中定义它,在这两种情况下都没有调用它。
第一种方法
invoke: {
id: "authenticateUser",
src: (c, e) => authenticateUserNew(c, e),
onDone: {
target: "authenticated",
actions: assign({ isAuthenticated: (context, event) => true }),
},
onError: {},
}第二种方法
invoke: {
id: "authenticateUser",
src: "authenticateUser",
onDone: {
target: "authenticated",
actions: assign({ isAuthenticated: (context, event) => true }),
},
onError: {},
}React version: ^17.0.2 xstate: ^4.3.5 @xstate/react: 2.0.1
发布于 2022-03-08 14:23:05
来自文档
调用是在具有invoke属性的状态节点配置中定义的。
相反,您尝试在事件节点中调用,而不是状态节点。
例如,您可以:
...
states: {
unauthenticated: {
on: {
AUTHENTICATE: {
target: 'authenticating'
},
},
},
authenticating: {
invoke: {
id: "authenticateUser",
src: 'authenticateUser',
onDone: {
target: "authenticated",
actions: assign({ isAuthenticated: (context, event) => true }),
},
onError: {
target: 'unauthenticated'
},
},
},
authenticated: {
on: {
LOGOUT: {
target: "unauthenticated",
},
},
},
},
...并发送AUTHENTICATE事件:
<button onClick={() => send("AUTHENTICATE")}>AUTHENTICATE</button>此外,我建议完全避免使用isAuthenticated。您可以检查是否已使用方法进行身份验证。
<h3>
isAuthenticated: {current.matches('authenticated') ? "True" : "False"}
</h3>https://stackoverflow.com/questions/71390147
复制相似问题