見出し画像

TypeScript & React & Firebase で何かつくってみる16 React Router2

昨日やり残したのは, 以下のようなルーティング処理だ.
1. / にアクセスする.
2. 「あたらしい部屋を作成」ボタンを押す.
3. firestore に /rooms/{ランダムなID} ドキュメントが作られ, 初期カード情報が作成される.
4. ユーザーは /rooms/{ランダムなID} に遷移する.

Switch

昨日参考にしたページに必要なことは大体書いてある.

Switch コンポーネントを使って URL に応じてコンポーネントを呼び分ける.

App.tsx

function App() {
 return (
   <BrowserRouter>
     <div className='App'>
       <div className='App-header'>
         <h2>Playing Cards</h2>
       </div>
       <Switch>
       <Route exact path='/' component={RoomBuilder}/>
       <Route path='/rooms/:roomId' component={CardGame}/>
       <Route path='*' children={<h1>Not Found</h1>} />
       </Switch>
     </div>
   </BrowserRouter>
 );
}

特に難しいことはない.
今まで全機能が CardGameコンポーネントにあったが, 部屋をつくるコンポーネントとして新しく RoomBuilder を用意する.

history

RoomBuilder 内で「あたらしい部屋をつくる」機能を実装するのはいい. CardGameコンポーネントから該当機能を引っ越してくるだけだ.

問題は 部屋ができたことを確認してから URL を  /rooms/{ランダムなID} に移動することだ.

・・・だが別に難しくなかった. これも参考サイトに書いてあった.

RoomBuilder.tsx

const RoomBuilder: React.FC = () => {
 // React Router の history API が React Hooks の一種として使える.
 const history = useHistory();

 const createRoom = async () => {
   // ランダムなIDを持つ部屋ドキュメントを生成する.
   const room = await firestore.collection('rooms').add({
     // 作成時刻 (一応書いとく)
     createAt: firebase.firestore.FieldValue.serverTimestamp(),
     // 今回のゲームで使用するカードの 全デザイン情報.
     surfaces, 
     // 今回のゲームで使用する 全カードデータ
     cards 
   });

   // 全カードを保持する「山」を作成して「場」に配置する.
   const deck = Engine.createDeck('spawn', cards);
   await Promise.all([
     room.collection('fields').doc('spawn').set(deck),
     room.collection('fieldViews').doc('spawn').set(Engine.createDeckView(deck)),
   ]);
   history.push(`/rooms/${room.id}`);
 }

 return (
   <div>
     <button onClick={e => createRoom()}>あたらしい部屋を作成</button>
   </div>
 );
}

firestore の rooms/ 以下に 新しい部屋ドキュメントを追加する.
ついでなので, 部屋ドキュメントに ゲームで使用するカード情報を書いておく. 今はスタティックだが, 後々は自由に作成できるようにしたい.

ゲームで使用するカードは, 部屋の作成と同時に登録・共有し, イカサマ防止の観点から ゲーム中は 一切変更しない (はず).

Engine は とりあえず作った名前空間?だ. いい名前が思いつかないので適当につけた. 他に説明せずに使っている関数があるかもしれないが きっとそれは重要ではない.

で, 肝心のURL遷移はというと, useHistory() というAPI で history オブジェクトを取得して, push() で 移動先パスを突っ込むだけ.

できた. ちゃんとURL も変わっている.

画像1

アニメーションにしたら 3コマだ. 


さて, 次はどうしようか.

この記事が気に入ったらサポートをしてみませんか?