比如说我们这台状态机想要给许多不同的店家共用,比如「绿洲酒吧」、「苹果旗舰店」...
难道我需要一直写一堆 appleStoreMachineConfig
, oasisBarMachineConfig
却只有 context 些微不一样吗?
答案是「不用的」
const createDoorMachine = (shopName) => {
return createMachine({
id: 'door',
// shopName 来自 function 参数
context: {
shopName
}
// ...
});
};
const appleStoreDoorMachine = createDoorMachine('苹果旗舰店');
const oasisBarDoorMachine = createDoorMachine('绿洲酒吧');
XState 的 machine 除了 someMachine.transition(state, event)
之外,也有提供方法 someMachine.withContext(...)
让我们能得到一台新的被动态加载 context 的状态机里。
const someContext = { shopName: "苹果旗舰店" };
const dynamicDoorMachine = doorMachine.withContext(someContext);
const service = interpret(dynamicDoorMachine).onTransition((state) => {
console.log(`State is ${state.value}`);
});
比如说今天我们「苹果旗舰店」想要改店名成「苹果尊绝不凡旗舰店」,我可以直接在状态机里面修改 context value 吗?
可以的! XState 官方提供给我们另外一个 API assign
(指派),让我们可以在 action 时,指定、修改 context 。
TLDR: codeSandbox DEMO
前情提要:Action 被触发的三种时机
让我们来看看如何修改店名,假设我们今天进开门时会看到 「苹果尊绝不凡旗舰店」关门时会看到「苹果旗舰店」的 LED 灯闪烁。
先来看看 assign
怎麽用!~ assign
是个 higher order function ,它会被先被定义 Action 发生时该怎麽更新 context,然後当实际 Action 发生时,就会去执行 assign
内被定义的修改方式!
assign
吃一个 object 参数,key 是想要被更新的 context value 的 key,以本例而言,就是我们的 shopName
而这个 object 的 value 会是什麽呢? 就是定义如何更新 context 的 function,这个 function 运算回传的结果,就是更新後的 context 。
assign({
shopName: (context, event) => "苹果旗舰店"
}),
assign({
shopName: (context, event) => "苹果尊绝不凡旗舰店"
}),
所以这个 assign 会被放在哪里呢?它可以被放在前情提要的三个地方
{
actions: {
拉开大门: () => console.error("side effect..........拉开厚重的门...."),
关上大门: () => console.error("side effect..........推回厚重的门...."),
+ "LED 显示": (context, event) => console.log(`${event.type}!~ LED 显示 『${context.shopName}』`),
}
}
开门时会看到 「苹果尊绝不凡旗舰店」关门时会看到「苹果旗舰店」的 LED 灯闪烁。
想必 我们应该是需要在 entry 进去 state 之前,先修改 context ,然後执行 "LED 显示" 的 side effect
因此我们会将这个需求定义在 entry action 里,前面提及 Action 可以有复数个...
我们在此新增定义进我们的 machineConfig,如此,进入到「开了」的状态之前,我们会先
"苹果尊绝不凡旗舰店"
"LED 显示"
来跟我们的客户打招呼 开了: {
entry: [
assign({
shopName: (context, event) => "苹果尊绝不凡旗舰店"
}),
"LED 显示"
],
on: {
关门: { target: "关着", actions: ["关上大门"] }
}
}
同理,进入到「关着」的状态之前,我们会先
"苹果旗舰店"
"LED 显示"
来跟我们的客户打招呼 关着: {
entry: [
assign({
shopName: (context) => "苹果旗舰店"
}),
"LED 显示"
],
on: {
开门: { target: "开了", actions: ["拉开大门"] }
}
},
明天~我将会努力举更贴近现实一点的例子 >_<
大家一起加油~~~!
https://xstate.js.org/docs/guides/context.html
https://xstate.js.org/docs/guides/action.html
表单 表单在实作上是件常见的的处理,为什麽会写这篇呢?实在是因为我太容易忘了 XD 还记得一开始接触...
从七月开始从零开始研究PySide2 GUI相关设计及程序如何撰写,已经有一段时间了,笔者深深有感,...
嗨嗨大家今天过得好吗?我今天成功煎了一颗蛋。今天的篇幅虽然看似有点短,但是里面的内容却是崭新且重要的...
刚体2D(Rigidbody 2D) 当物体运动速度远小於光速可被视为理想刚体,可以忽略型变,也就是...
Review 由於 State 原本可以一篇写完的,被我拖成四篇的关系,所以来回顾一下,哈哈哈哈哈哈...