xstate 初探 (2): 使用 spawn / send 建立 widget state machine 與父層傳遞事件溝通

Luc Humanhighway
4 min readJul 17, 2020

--

基本上當專案的元件複雜度都高到一個程度時,只有一個 state machine 是無法滿足專案的狀態變化需求,所以需要再規劃架構時對每個元件的複雜度建立不同的 state machine.。所以本文目的是實作父層如何建立子層的 state machine 並互相溝通。

在實作前可以先大致了解一下 spawn actor章節。xstate 除了核心的 fsm 架構之外,還引用了 actor model 來達到關注點分離。

關於 actor model 幾項特性:

  • actor 可以建立一或多個 actor.
  • actor 透過 message ( 在 xstate 裡指的是 event )與其他 actor 溝通。
  • actor 可以指定如何處理下一個 message.
  • actor 有自己的 local state 並且處於 isolate 狀態。
  • actor 是輕量的,容易被建立。

也因為 actor model 特性,所以 machine 與 machine 之間溝通透過 event 來傳遞,並在各自的 local state 做資料處理。

actor model 相關資料放在文末

實作 Widget List

以一個簡單的 widget list 為例,父容器 List 可以透過事件發送給子容器 Widget 更新資料,而子容器的 Widget 可往上發送事件給父層刪除資料。

先看已完成的範例: Widget List 與 Widget 有各自獨立的 state machine. 並且有各自的 loading / idle 狀態。widget list 可以統一發送更新時間的事件, 而 widget 的移除按鈕點選可呼叫上層 machine event 刪除 widget 相關 context 資料。

xstate-widgets-demo

主要的程式碼是著重在 widgetListMachinewidgetMachine 這兩個 machine config.

widgetListMachine.js
widgetMachine.js

要點:

  • 上層建立子 widget 的 state machine: 上層的 widgetListMachine 在 loading state 透過 invoking promise 跟後端要相關資料,並在 onDone 時透過 spawn 建立的 actor+ Machine.withContext建立 widgetMachine 及初始 context.
  • 上層發送事件給 widget: 請參考 widgetListMachine updateTimeToWidgets action,使用 pure action 建立動態 actions 並從 context 取出 actor 逐一 send action。而在 widgetMachine updateTime action 則收到發出的 update Time event 並取得更新資料。
  • widget 發送事件給上層: 請參考 widgetMachine 的 remove action 透過 sendParent 送出事件並 tigger widgetListMachine 的 removeWidget action. 然後再更新上層的 context 資料移除掉 widget.

reference:

actor model reference:

--

--

Luc Humanhighway

Always a frontend & web game developer. sometimes a music storyteller.