Skip to content

kcg-edu-future-lab/madoi-client-react

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

27 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

madoi-client-react

A React library for Distributed Sharing Platform: Madoi.

分散共有基盤MadoiのReact用クライアントライブラリ。

Current Release Licence

Install

npm i madoi-client madoi-client-react

Getting started

Prepare Madoi instance

const MadoiContext = createContext({
    madoi: new Madoi("wss://host/madoi-server/rooms/room000", "MADOI_API_KEY")
});

最初にMadoiクライアントを作成してください。引数はMadoiサーバのURLとAPIキーです。あらかじめ、Madoiサーバを起動しておく必要があります。

Example for shared state (useSharedState)

function StateExample(){
  const ctx = useContext(MadoiContext);
  const [msg, setMsg] = useSharedState(ctx.madoi, "hello");
  const onClick: MouseEventHandler = ()=>{
    // setメソッドに渡された状態は、全てのアプリケーションに共有される
    setMsg(v => v === "hello" ? "world" : "hello");
  }
  return <div>
      <h4>madoi state</h4>
      <button onClick={onClick}>{msg}</button>
    </div>;
}

useSharedState は、useState の分散共有版です。 同じMadoiサーバ上のルームに参加しているアプリケーション間で、状態の同期が行われます。 上記の例では、一つのアプリケーション内で setMsg が実行されると、新しい状態が全てのアプリケーションに通知され、既存の状態と異なる場合はReactのレンダリングが行われます。 クリックハンドラで setMsg が呼び出されているので、ボタンがクリックされるたびに全てのアプリケーションでラベルが変更されます。

useSharedState は、手軽に利用できる反面、毎回状態を送信するため、サイズが大きい場合(例えば画像の場合)は通信コストが増大します。 また、利用者間で状態変更操作が競合しやすいという欠点があります(例えば画像に対して2人が同時に描画した場合、後で描画した方の状態で上書きされてしまう)。

次に紹介する useMadoiModel は、状態の更新操作を個別に共有するため、競合の回避が行いやすい方式です。

Example for shared model (useMadoiModel)

/*
 * チャットログを保持するモデルクラス
 */
class ChatLogs{
  private logs: string[] = [];

  // ルーム内の他のアプリケーションでも実行するメソッドには@Distributedデコレータを追加する
  // 状態を変更するメソッドには@ChangeStateデコレータを追加する
  @Distributed()
  @ChangeState()
  addLog(text: string){
    this.logs = [...this.logs, text];
  }

  // 状態を取得するメソッドには@GetStateデコレータを追加する
  @GetState()
  getLogs(){
    return this.logs;
  }

  // 状態を設定するメソッドには@SetStateデコレータを追加する
  @SetState()
  setLogs(logs: string[]){
    this.logs = logs;
  }
}

function ModelExample(){
  const ctx = useContext(MadoiContext);
  const inputRef = useRef<HTMLInputElement>(null!);
  const logs = useMadoiModel(ctx.madoi, ()=>new ChatLogs());

  const onSubmit: FormEventHandler = e=>{
    e.preventDefault();
    // @Distributedが指定されたメソッドは、他の全てのアプリケーションでも実行される
    logs.addLog(inputRef.current.value);
  }

  return <div>
    <h4>madoi model</h4>
    <form onSubmit={onSubmit}>
      <input ref={inputRef} type="text"></input>
    </form>
    <div>
      {logs.getLogs().map(l => <div>{l}</div>)}
    </div>
  </div>;
}

useMadoiModel は、状態を保持し、かつ状態への変更操作を持っているオブジェクトを登録します。 登録したオブジェクトの@Distributed()が指定されたメソッドが実行されると、他の全てのアプリケーションでも実行されます。 より厳密には、実行がMadoiライブラリにより横取りされ、引数とともにサーバへ送信され、全てのアプリケーションに送信され、 アプリケーションで受信した際にメソッドが実行されます。 複数のクライアントで同時にメソッドが実行された場合も、サーバに届いた順にアプリケーションへ送信されるため、全てのアプリケーションでメソッドの実行順は同じになります。

@ChangeState()が指定されたメソッドが実行されると、状態取得メソッド(@GetStateが指定されたメソッド)が実行され、状態が取得されます。 次に、取得した状態と、実行前の状態との比較が行われ、変更されていれば、Reactのレンダリングが行われます。 また、状態はMadoiサーバにも送信され、アプリケーションが新しく参加してくれば、そのアプリケーションに通知されます。

これにより、チャットログの追加や画像への描画など、異なるアプリケーションで同時に起こりうる操作を、 取りこぼすことなくオブジェクトに反映できます。

まとめ

madoi-client-reactにより、MadoiとReactを組み合わせ、分散共有アプリを宣言的な記述で設計、実装できます。

より具体的なアプリケーション開発例は、ビデオ会議付きコラボレーションツール Presenceを参照ください。

About

A React library for Distributed Sharing Platform: Madoi.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors