チュートリアル: MoonBit

クライアントへの State 渡し

サーバーからクライアントにデータを渡します。

問題

サーバーデータをクライアント JavaScript にどうやって渡しますか?

サーバー(MoonBit)            クライアント(TypeScript)
     │                              │
     │  データ付き HTML をレンダリング │
     │ ──────────────────────────>  │
     │                              │
     │      props をどう渡す?       │
     └──────────────────────────────┘

解決策

Luna は状態を JSON として HTML にシリアライズ。

サーバーサイド(MoonBit)

struct CounterState {
  initial : Int
  max : Int
} derive(ToJson)

fn counter_island(state : CounterState) -> @luna.Node {
  island(
    id="counter",
    url="/static/counter.js",
    state=state.to_json().stringify(),
    trigger=Load,
    children=[
      div([
        button([text("Count: " + state.initial.to_string())])
      ])
    ],
  )
}

クライアントサイド(TypeScript)

interface CounterProps {
  initial: number;
  max: number;
}

function Counter(props: CounterProps) {
  const [count, setCount] = createSignal(props.initial);

  const increment = () => {
    setCount(c => Math.min(c + 1, props.max));
  };

  return (
    <button onClick={increment}>
      Count: {count()} / {props.max}
    </button>
  );
}

hydrate("counter", Counter);

複雑な State

ネストした構造体

struct UserCardState {
  user : User
  settings : Settings
} derive(ToJson)

struct User {
  id : Int
  name : String
  email : String
} derive(ToJson)

struct Settings {
  theme : String
  compact : Bool
} derive(ToJson)

配列

struct TodoListState {
  todos : Array[Todo]
  filter : String
} derive(ToJson)

struct Todo {
  id : Int
  text : String
  done : Bool
} derive(ToJson)

セキュリティ考慮事項

状態に機密データを含めないこと:

// 悪い例 - HTML ソースに公開される
struct BadState {
  api_key : String    // やめて!
  password : String   // 絶対だめ!
}

// 良い例 - 公開データのみ
struct GoodState {
  user_id : Int
  display_name : String
}

試してみよう

商品ページ Island の状態構造を設計

次へ

Islands Triggers → について学ぶ