舉例來說:
所有可互動的都有狀態
feat. 冠群的 slide
先由使用者互動改變狀態
畫面會依據不同的狀態去顯示
管理 資料 和 使用者操作事件 的互動流程
一個可預測的狀態容器
單向資料流
將狀態視作一連串的狀態流
每次的事件都是產生一個新的狀態
雙向資料綁定 → 連鎖更新
不容易去預測一個單一互動所造成的改變結果
MVC 只定義了三個角色的功能與關係
有了 FLUX 能更明確的定義「與資料互動的方式」
Single Store : Single Source of Truth
Finite State Machine (FSM) & Statechart based
有限個狀態以及在這些狀態之間的轉移和動作等行為的數學模型
例如:紅綠燈
( FSM 是很嚴謹的模型,這邊只是粗淺介紹 )
簡言之 就是 定義 各狀態 ( State ) 和 過渡方法 ( Action )
import React from 'react';
import { useMachine } from '@xstate/react';
import { lightMachine } from './lightMachine';
function App() {
  const [state, send] = useMachine(lightMachine);
  return (
    <div className="App">
      {state.matches(LIGHT_STATES.RED) && <RedLight />}
      {state.matches(LIGHT_STATES.GREEN) && <GreenLight />}
      {state.matches(LIGHT_STATES.YELLOW) && <YellowLight />}
      <button
        onClick={() => {
          send(LIGHT_EVENTS.CLICK);
        }}
      >
        click me
      </button>
    </div>
  );
}import { Machine } from 'xstate';
const LIGHT_STATES = {
  RED: 'RED',
  GREEN: 'GREEN',
  YELLOW: 'YELLOW',
};
const LIGHT_EVENTS = {
  CLICK: 'CLICK',
};
export const lightMachine = Machine({
  initial: LIGHT_STATES.RED,
  states: {
    [LIGHT_STATES.RED]: {
      on: {
        [LIGHT_EVENTS.CLICK]: LIGHT_STATES.GREEN,
      },
    },
    [LIGHT_STATES.GREEN]: {
      on: {
        [LIGHT_EVENTS.CLICK]: LIGHT_STATES.YELLOW,
      },
    },
    [LIGHT_STATES.YELLOW]: {
      on: {
        [LIGHT_EVENTS.CLICK]: LIGHT_STATES.RED,
      },
    },
  },
});資料改變 或 使用者觸發事件 後產生的後續影響
運算的過程中,改變了系統狀態或是對外部世界進行交互。
如:非同步請求( Network Request )而產生的資料不一致
本身自己不處理 Side Effect,依賴於 其他套件處理 ( middleware )
import {
  createStore,
  combineReducers,
  compose,
  applyMiddleware,
} from 'redux';
import thunk from 'redux-thunk';
const store = createStore(combineReducers({
}), {}, compose(
  applyMiddleware(
    thunk,
  ),
));
export default store;優
優
缺
缺
One More Thing
Flow Control in FSM
Shopping
Login
Payment
Pending
Success
idle
type Payload =
  | {
      step: 'idle';
    }
  | PayloadShopping
  | PayloadLogin
  | PayloadPayment
  | PayloadPending
  | PayloadSucess;interface PayloadShopping {
  step: 'shopping';
  customerInfo: CustomerInfo | undefined;
  items: ShoppingCartItemData[];
}
interface PayloadLogin extends Omit<PayloadShopping, 'step'> {
  step: 'login';
}
interface PayloadPayment extends Omit<PayloadLogin, 'step'> {
  accessToken: string;
  step: 'payment';
}
interface PayloadPending extends Omit<PayloadPayment, 'step'> {
  receivedAmount: number;
  step: 'pending';
}
interface PayloadSucess extends Pick<PayloadPending, 'receivedAmount'> {
  payment: CheckoutCashPaymentMutation_payment;
  step: 'success';
}{payload.step === 'idle' && (
  <EnterCustomerNoModal
    onNextStep={...}
  />
)}
{payload.step === 'shopping' && (
  <Shopping
    payload={...}
    onGoBack={...}
    onCheckout={...}
  />
 }
 {payload.step === 'login' && (
   <Login
      payload={...}
      onGoBack={...}
      onCheckout={...}
    />
 )}
 {payload.step === 'payment' && (
   <Payment
      payload={...}
      onGoBack={...}
      onPayment={...}
    />
 )}
 {payload.step === 'pending' && (
  <Pending
      payload={...}
      onGoBack={...}
      onSuccess={...}
    />
 )}
 {payload.step === 'success' && (
  <Success
      payload={...}
      onGoBack={...}
      onOk={...}
    />
 )}