XState React - 未触发调用服务
XState React - Invoke Service not triggered
我正在使用 xstate
和 react
来实现基本的登录功能。代码是 here,我面临的问题是,在事件 AUTHENTICATING
中,它旨在调用服务 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
来自docs:
An invocation is defined in a state node's configuration with the invoke property
您正在尝试在 事件节点 中调用,而不是在状态节点中调用。
例如,您可以这样做:
...
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
。您可以检查您是否通过了 matches
method:
的身份验证
<h3>
isAuthenticated: {current.matches('authenticated') ? "True" : "False"}
</h3>
我正在使用 xstate
和 react
来实现基本的登录功能。代码是 here,我面临的问题是,在事件 AUTHENTICATING
中,它旨在调用服务 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
来自docs:
An invocation is defined in a state node's configuration with the invoke property
您正在尝试在 事件节点 中调用,而不是在状态节点中调用。
例如,您可以这样做:
...
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
。您可以检查您是否通过了 matches
method:
<h3>
isAuthenticated: {current.matches('authenticated') ? "True" : "False"}
</h3>