47
33

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

React HooksAdvent Calendar 2019

Day 7

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

Last updated at Posted at 2019-12-06

はじめに

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

react-firebase-hooks

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

https://github.com/CSFrequency/react-firebase-hooks

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

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

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

テストデータの作成

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

image.png

コーディング

モジュールの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

https://codesandbox.io/s/wonderful-browser-zh0wc

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

image.png

おわりに

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

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

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

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

47
33
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
47
33

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?