我有两台机器:AuthenticationMachine
和AddressMachine
。 Login component
使用AuthenticationMachine,Address component
使用AddressMachine。但是我需要来自AddressMachine的token
地址组件中的地址才能与AddressMachine一起使用。我曾尝试在AuthenticationMachine中生成Actor
,但没有用。
身份验证机器
const createService = (context: {token: string}) => {
return Machine({
id: 'service',
initial: 'logged_in',
states: {
logged_in: {},
logged_out: {},
},
}).withContext(context);
};
const authenticationMachine = Machine(
{
id: 'authenticationMachine',
initial: 'unauthenticated',
context: {
token: undefined,
error: undefined,
service: undefined,
},
states: {
unauthenticated: {
on: {
LOGIN: 'authenticating',
},
},
authenticating: {
invoke: {
src: 'login',
onDone: {
target: 'loggedIn',
actions: assign({
token: (ctx, event: any) => event.data.access_token,
service: (ctx, event) => {
return spawn(createService({token: event.data.access_token}));
},
}),
},
onError: {
target: 'unauthenticated',
actions: assign({
error: (ctx, event: any) => event.data,
}),
},
},
},
loggedIn: {
on: {
LOGOUT: 'unauthenticated'
},
},
},
},
);
答案 0 :(得分:0)
我认为这可能是您使用Assign或只是实现问题组件的方式。
中组件中的机器的有效示例还有一个简单的示例,说明如何在组件中使用机器:
地址组件:
function Address(props) {
const [current] = useService(props.service);
return <>Address Component token: {current.context.token}</>;
}
登录组件:
export default function Login() {
const [current, send] = useMachine(authenticationMachine);
const isUnauthenticated = current.matches("unauthenticated");
const isAuthenticating = current.matches("authenticating");
const isLoggedIn = current.matches("loggedIn");
if (isUnauthenticated) {
return (
<>
token: {current.context.token}
<br />
<button onClick={() => send("LOGIN")}>Login</button>
</>
);
}
if (isAuthenticating) {
return <>...hold on, authenticating</>;
}
if (isLoggedIn) {
return (
<>
token: {current.context.token}
<br />
<button onClick={() => send("LOGOUT")}>Logout</button>
<br />
<Address service={current.context.service} />
</>
);
}
}
您的机器示例已展开:
import { assign, Machine, spawn } from "xstate";
const createService = (context: { token: string }) => {
return Machine({
id: 'service',
initial: 'logged_in',
states: {
logged_in: {},
logged_out: {},
},
}).withContext(context);
};
const login = (ctx) => {
const { email, pw } = ctx;
return new Promise((resolve, reject) => {
if(email === 'a@b.c' && pw === 'abc') {
return resolve({ token: 'jahsfjkhakjsnfj'});
} else {
return reject({ token: undefined });
}
});
};
const authenticationMachine = Machine(
{
id: 'authenticationMachine',
initial: 'unauthenticated',
context: {
token: undefined,
error: undefined,
service: undefined,
email: 'a@b.c',
pw: 'abc'
},
states: {
unauthenticated: {
on: {
LOGIN: 'authenticating',
},
},
authenticating: {
invoke: {
id: 'login',
src: context => login(context),
onDone: {
target: 'loggedIn',
actions: [
assign({ token: (_, event) => event.data.token }),
assign({ service: (_, event) => {
return spawn(createService({token: event.data.token}));
}})
]
},
onError: { target: 'unauthenticated' },
},
},
loggedIn: {
on: {
LOGOUT: 'unauthenticated'
},
},
},
}
);
export { authenticationMachine };