XState react - 跨多个组件共享机器实例
Posted
技术标签:
【中文标题】XState react - 跨多个组件共享机器实例【英文标题】:XState react - share machine instance across multiple components 【发布时间】:2020-03-28 04:08:35 【问题描述】:我有两台机器:AuthenticationMachine
和 AddressMachine
。 AuthenticationMachine 由 Login component
使用,而 AddressMachine 由 Address component
使用。但是我需要地址组件中来自AuthenticationMachine 的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'
,
,
,
,
);
【问题讨论】:
【参考方案1】:我认为这可能是您对 assign 的使用,或者只是您实现组件的方式有问题。
这是您的机器在 codesandbox 中的组件的工作示例
另外,还有一个简单的例子,说明如何在组件中使用机器:
地址组件:
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 ;
【讨论】:
我考虑过使用这种方法来解决问题。我已经在一个 react 项目中尝试过这种方法并且效果很好,但是我使用的是 react native 和 react 导航。我不能传递道具。 如何使用 screenProps 像这篇文章中详述的那样,medium.com/@benfox_63249/… ? 我无法提供更多帮助,因为我没有真正使用 react-native 的经验 反应导航路由器不像你在网络上那样接受子路由,它提供了一个函数,例如返回的 createStackNavigator 函数 - 我猜是一个组件。我尝试了一些我在网上找到的不同方法来传递 screenProps,但没有添加道具。以上是关于XState react - 跨多个组件共享机器实例的主要内容,如果未能解决你的问题,请参考以下文章
有没有办法在 useEffect 的反应组件中设置 xstate 机器的状态?
Apollo GraphQL (React) 跨组件数据共享