iT邦幫忙

2021 iThome 鐵人賽

DAY 20
0
Software Development

From State Machine to XState系列 第 20

Day20 - 在 XState 與 Side Effect 互動吧~ action API

  • 分享至 

  • xImage
  •  

1. Action 與 Side Effect

https://ithelp.ithome.com.tw/upload/images/20210926/20130721htU67KKipL.png
昨天,我們確認了狀態能被儲存起來,然而我們這個開門,只是狀態轉換成「開了」這個字串而已,我們沒有實際執行任何 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 個地方被執行

  • 一個是離開 (Exit) 時的 Action,指得是當你要離開 (exit) 某個狀態時,你要執行的 side effect
  • 一個是轉移 (Transition) 時的 Action,指得是當你在狀態轉移 (transition) 的過程中,要執行的 side effect
  • 最後是要進入 (Enter) 時的 Action,指得是當你要進入 (enter) 某個狀態時,要要執行的 side effect

2. 需求探討

https://ithelp.ithome.com.tw/upload/images/20210926/20130721htU67KKipL.png

那此時我們要來界定 實際上「拉開大門」跟「關上大門」的 side effect 是哪種 action 呢?

這個範例滿有趣的~因為...

「開了」一定只會回到「關著」
「關著」一定只會回到「開了」

一體兩面,那究竟是該把「拉開大門」、「關上大門」要放在 Entry action or Exit action or Transition action 呢??

以關門為例

  1. 選擇採用 Entry Action 的話,當 state 要 進入「關著」狀態時,就要執行「關上大門」 side effect
  2. 選擇採用 Exit Action 的話,當 state 要 離開「開了」狀態時,就要執行「關上大門」 side effect
  3. 選擇採用 Transition Action 的話,當 state 在「開了」轉移「關著」的過程時,就要執行「關上大門」 side effect

還是有些微差異,不過這就是看各自的商業需求了

  1. 放在 Entry 的話...
    因為 machine 的 service 一被建立之後,就會進入到初始狀態「關著」,所以 onEntry 會被呼叫
    https://ithelp.ithome.com.tw/upload/images/20211005/20130721Ru8KCZsMJZ.png

  2. 放在 Exit 的話...
    因為 machine 的 service 一被停止之後,就會關閉狀態機,離開最後一個狀態,所以 onExit 會被呼叫
    https://ithelp.ithome.com.tw/upload/images/20211005/20130721TEz8j3Eevx.png

  3. 放在 Transition 的話...
    就會跟我們某個轉移事件底下把 target, actions 放在一起,為啥是 actions 呢?因為 side effect 可以同時執行很多個,依照本狀態機的現實情境,可能會比較適合將 side effect 放在 Transition Action
    https://ithelp.ithome.com.tw/upload/images/20211006/20130721LhfLD50olc.png


3. XState 的 action API

那具體來說 Action 該怎麼被寫在 XState 呢?其實就跟 states , events 一樣!可以一開始就先寫在 Machine 的 config~

TLDR:
codesandbox DEMO

3.1 描述你的 Actions

首先將 Action 的描述放在 createMachine 的第二個參數 extraOptions

import { createMachine } from "xstate";
const doorMachine = createMachine(machineConfigs, extraOptions)

那今天只學習到 Actions 相關的 option ,我們先給一個 key 為 actions 的 object

這個 object 裡面的 keyAction Namevalue 是 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 是什麼東西,會在明天為大家介紹


3.2 更新你的 Machine Config

3.2-1 採用 Entry 的話

 states: {
      關著: {
        entry: "關上大門", // 一個 action 可以用字串
        on: {
          開門: { target: "開了"}
        }
      },
      開了: {
        entry: ["拉開大門"], // 多個 action 可以用 array
        on: {
          關門: { target: "關著" }
        }
      }
    }

3.2-2 採用 Exit 的話

 states: {
      關著: {
        on: {
          開門: { target: "開了" }
        }
        exit: "拉開大門"
      },
      開了: {
        on: {
          關門: { target: "關著" }
        }
        exit: ["關上大門"]
      }
    }

3.2-3 採用 Transition 的話

    states: {
      關著: {
        on: {
          開門: {
            target: "開了",
            actions: ["拉開大門"]
          }
        }
      },
      開了: {
        on: {
          關門: { target: "關著", actions: ["關上大門"] }
        }
      }
    }

codesandbox DEMO

參考文獻

https://xstate.js.org/docs/guides/actions.html


上一篇
Day19 - Interpreting Machines - 2 :使用 interpret API
下一篇
Day21 - 在 XState, 狀態機器裡無窮盡的狀態、 資料:Extended State and context - 1
系列文
From State Machine to XState31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0

趕稿中 哈哈哈哈哈

Ken Chen iT邦新手 4 級 ‧ 2021-10-06 00:37:29 檢舉

被笑了 嗚嗚嗚 大大真兇

我要留言

立即登入留言