react-firebase-hooksを使ってみた(Firestore Hooks編)


はじめに

前回の記事でreact-firebase-hooksのAuth Hooksを使ってみたのですが、今回はFirestore Hooksに挑戦したいと思います。

react-firebase-hooks

リポジトリはこちらです。

このライブラリは、4種類のAPIを提供しています。

  • Auth Hooks
  • Cloud Firestore Hooks
  • Cloud Storage Hooks
  • Realtime Database Hooks

今回対象とするのは2つ目のFirestore Hooksです。

テストデータの作成

最初に、Firestoreのコンソールでコレクションといくつかのドキュメントを作成します。コレクション名はtodosとしました。

コーディング

モジュールのimport

今回使うモジュールをimportします。

import React, { useState } from "react";
import ReactDOM from "react-dom";

import firebase from "firebase";
import { useCollectionData } from "react-firebase-hooks/firestore";

TodoListコンポーネント

todosコレクションを表示するコンポーネントを作ります。

const TodoList = () => {
  const [values, loading, error] = useCollectionData(
    firebase.firestore().collection("todos"),
    { idField: "id" }
  );
  if (loading) {
    return <div>Loading...</div>;
  }
  if (error) {
    return <div>{`Error: ${error.message}`}</div>;
  }
  return (
    <ul>
      {values.map(value => (
        <li key={value.id}>{value.title}</li>
      ))}
    </ul>
  );
};

idFieldでidを取得するところがポイントです。

NewTodoコンポーネント

todosコレクションに新たなドキュメントを追加するためのコンポーネントを作ります。

const NewTodo = () => {
  const [title, setTitle] = useState("");
  const [pending, setPending] = useState(false);
  const add = async () => {
    setTitle("");
    setPending(true);
    try {
      await firebase
        .firestore()
        .collection("todos")
        .add({ title });
    } finally {
      setPending(false);
    }
  };
  return (
    <div>
      <input value={title} onChange={e => setTitle(e.target.value)} />
      <button type="button" onClick={add}>
        Add
      </button>
      {pending && "Pending..."}
    </div>
  );
};

エラー処理は省略しています。

Appコンポーネント

最後に、全体をつなげるAppコンポーネントとReactDOMのrenderです。

const App = () => {
  return (
    <div>
      <TodoList />
      <NewTodo />
    </div>
  );
};

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

CodeSandbox

完成したものがこちらです、実際に動作させるためにはforkしてfirebaseConfigを置き換える必要がありますのでご注意ください。

おわりに

Firestoreのリアルタイム更新とReact Hooksはとても相性がいいと感じました。ドキュメントを追加したら、すぐに更新されます。Firestoreのコンソールから追加しても同様です。

今回は、useCollectionDataを使いましたが、用意されているhooksはさらにあります。

  • useCollection
  • useCollectionOnce
  • useCollectionData
  • useCollectionDataOnce
  • useDocument
  • useDocumentOnce
  • useDocumentData
  • useDocumentDataOnce

Once系は一度だけの取得なのですが、その場合はhookがどれだけ役立つかは微妙です。callbackから使うことになることが多い気がします。また、Data系のhookはTypeScriptの型が付けられますが、ソースコード上は単にアサーションしているだけなので、予期せぬランタイムエラーが発生する可能性がありそうです。結局、独自の拡張をしようと思うとcustom hooksを作ることになりそうですが、その先に本ライブラリのhooksから合成できるかはやってみないと分からないといった感じになりそうです。