昨天,我們確認了狀態能被儲存起來,然而我們這個開門,只是狀態轉換成「開了」這個字串而已,我們沒有實際執行任何 Side Effect 來開門,還記得我們在 Day 11 提及 Action 嗎?
Action 就是狀態機對外與 Side Effect 溝通互動的方式之一。
斯斯有兩種,啊不是~是 Action 有三種
- entry actions are executed upon entering a state
- exit actions are executed upon exiting a state
- transition actions are executed when a transition is taken.
by XState - action
Actions are most commonly triggered on entry or exit of a state, although it is possible to place them on a transition itself.
by StateCharts.dev
這裡 XState 和 StateCharts.dev 官網介紹到,作為 action 的 side effect 可以在 3 個地方被執行
那此時我們要來界定 實際上「拉開大門」跟「關上大門」的 side effect 是哪種 action 呢?
這個範例滿有趣的~因為...
「開了」一定只會回到「關著」
「關著」一定只會回到「開了」
一體兩面,那究竟是該把「拉開大門」、「關上大門」要放在 Entry action or Exit action or Transition action 呢??
還是有些微差異,不過這就是看各自的商業需求了
放在 Entry 的話...
因為 machine 的 service 一被建立之後,就會進入到初始狀態「關著」,所以 onEntry 會被呼叫
放在 Exit 的話...
因為 machine 的 service 一被停止之後,就會關閉狀態機,離開最後一個狀態,所以 onExit 會被呼叫
放在 Transition 的話...
就會跟我們某個轉移事件底下把 target, actions 放在一起,為啥是 actions 呢?因為 side effect 可以同時執行很多個,依照本狀態機的現實情境,可能會比較適合將 side effect 放在 Transition Action
那具體來說 Action 該怎麼被寫在 XState 呢?其實就跟 states , events 一樣!可以一開始就先寫在 Machine 的 config~
TLDR:
codesandbox DEMO
首先將 Action 的描述放在 createMachine 的第二個參數 extraOptions
import { createMachine } from "xstate";
const doorMachine = createMachine(machineConfigs, extraOptions)
那今天只學習到 Actions 相關的 option ,我們先給一個 key 為 actions 的 object
這個 object 裡面的 key
是 Action Name;value
是 callback function,當你在 machineConfigs
定義 entry / exit / transition 要執行什麼 action 時,就可以使用這組 Action Name 指名
const doorMachine = createMachine(machineConfigs,
{
actions: {
拉開大門: (c, e) =>
console.error("side effect..........拉開厚重的門...."),
關上大門: () => console.error("side effect..........推回厚重的門....")
}
}
)
這邊暫時不介紹 callback function (c, e)=>...
可以拿到的 c, e 是什麼東西,會在明天為大家介紹
states: {
關著: {
entry: "關上大門", // 一個 action 可以用字串
on: {
開門: { target: "開了"}
}
},
開了: {
entry: ["拉開大門"], // 多個 action 可以用 array
on: {
關門: { target: "關著" }
}
}
}
states: {
關著: {
on: {
開門: { target: "開了" }
}
exit: "拉開大門"
},
開了: {
on: {
關門: { target: "關著" }
}
exit: ["關上大門"]
}
}
states: {
關著: {
on: {
開門: {
target: "開了",
actions: ["拉開大門"]
}
}
},
開了: {
on: {
關門: { target: "關著", actions: ["關上大門"] }
}
}
}
https://xstate.js.org/docs/guides/actions.html