madoi-client-react
v0.2.0
Published
A React Utilities for Madoi Client
Maintainers
Readme
madoi-client-react
A React library for Distributed Sharing Platform: Madoi.
分散共有基盤MadoiのReact用クライアントライブラリ。
Install
npm i madoi-client madoi-client-reactGetting 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人が同時に描画した場合、後で描画した方の状態で上書きされてしまう)。
次に紹介する useSharedModel は、状態の更新操作を個別に共有するため、競合の回避が行いやすい方式です。
Example for shared model (useSharedModel)
/*
* チャットログを保持するモデルクラス
*/
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 = useSharedModel(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>;
}useSharedModel は、状態を保持し、かつ状態への変更操作を持っているオブジェクトを登録します。
登録したオブジェクトの@Distributed()が指定されたメソッドが実行されると、他の全てのアプリケーションでも実行されます。
より厳密には、実行がMadoiライブラリにより横取りされ、引数とともにサーバへ送信され、全てのアプリケーションに送信され、
アプリケーションで受信した際にメソッドが実行されます。
複数のクライアントで同時にメソッドが実行された場合も、サーバに届いた順にアプリケーションへ送信されるため、全てのアプリケーションでメソッドの実行順は同じになります。
@ChangeState()が指定されたメソッドが実行されると、状態取得メソッド(@GetStateが指定されたメソッド)が実行され、状態が取得されます。
次に、取得した状態と、実行前の状態との比較が行われ、変更されていれば、Reactのレンダリングが行われます。
また、状態はMadoiサーバにも送信され、アプリケーションが新しく参加してくれば、そのアプリケーションに通知されます。
これにより、チャットログの追加や画像への描画など、異なるアプリケーションで同時に起こりうる操作を、 取りこぼすことなくオブジェクトに反映できます。
まとめ
madoi-client-reactにより、MadoiとReactを組み合わせ、分散共有アプリを宣言的な記述で設計、実装できます。
より具体的なアプリケーション開発例は、ビデオ会議付きコラボレーションツール Presenceを参照ください。
