React-Firebase-Hooks VS React-Query-Firebase

# 初めに
業務システムの開発で **`firebase`** を使おうとなった時に`firebase SDK`をそのまま使用したくないと思ったので (SDKにあまり依存させたくないという思い) 何かライブラリなどないかと調べたところ本記事タイトルの[React-Firebase-Hooks](https://react-query-firebase.invertase.dev/) と[React-Query-Firebase](https://github.com/CSFrequency/react-firebase-hooks) を見つけたので両者の検証, 比較をしようと思います。

# Firestoreからのデータ取得
`Firestore Database`からのデータ取得の実装コードです。
## React-Firebase-Hooks
```tsx
import { collection } from 'firebase/firestore';
import React from 'react';
import { useCollection } from 'react-firebase-hooks/firestore';

import { db } from '@/lib/firebase';

const ReactFirebaseHooksSample = () => {
  const [snapshot, isLoading, error] = useCollection(collection(db, 'users'), {
    snapshotListenOptions: { includeMetadataChanges: true },
  });

  return (
    <div>
      <p>
        {error && <strong>Error: {JSON.stringify(error)}</strong>}
        {isLoading && <span>Collection: Loading...</span>}
        {snapshot && (
          <span>
            Collection:{' '}
            {snapshot.docs.map((doc) => (
              <React.Fragment key={doc.id}>{JSON.stringify(doc.data())}, </React.Fragment>
            ))}
          </span>
        )}
      </p>
    </div>
  );
};
```
## React-Query-Firebase
```tsx
import { useFirestoreQuery } from '@react-query-firebase/firestore';
import { collection, query } from 'firebase/firestore';
import React from 'react';

import { db } from '@/lib/firebase';

const ReactFirebaseHooksSample = () => {
  const ref = query(collection(db, 'users'));
  const usersQuery = useFirestoreQuery(['users'], ref);
  const { data: snapshot, isLoading, error } = usersQuery;

  return (
    <div>
      <p>
        {error && <strong>Error: {JSON.stringify(error)}</strong>}
        {isLoading && <span>Collection: Loading...</span>}
        {snapshot && (
          <span>
            Collection:{' '}
            {snapshot.docs.map((doc) => (
              <React.Fragment key={doc.id}>{JSON.stringify(doc.data())}, </React.Fragment>
            ))}
          </span>
        )}
      </p>
    </div>
  );
};
```
# Firebase Authを利用したログイン・ログアウト
`Firestore Authentication`を利用した認証周りの実装コードです。
## React-Firebase-Hooks
```tsx
import { signInWithEmailAndPassword, signOut } from 'firebase/auth';
import React from 'react';
import { useAuthState } from 'react-firebase-hooks/auth';

import { auth } from '@/lib/firebase';

const login = async () => {
  await signInWithEmailAndPassword(auth, 'test@gmail.com', 'password');
};
const logout = async () => {
  await signOut(auth);
};

const ReactFirebaseHooksSample = () => {
  const [user, isLoading, error] = useAuthState(auth);

  return (
    <div>
      <p>
        {error && <strong>Error: {error}</strong>}
        {isLoading && <span>Collection: Loading...</span>}
      </p>
      {user && (
        <div>
          <p>Current User: {user.email}</p>
          <button onClick={logout}>Logout</button>
        </div>
      )}
      <button onClick={login}>Login</button>
    </div>
  );
};
```
## React-Query-Firebase
```tsx
import { useAuthUser } from '@react-query-firebase/auth';
import { signInWithEmailAndPassword, signOut } from 'firebase/auth';
import React from 'react';

import { auth } from '@/lib/firebase';

const login = async () => {
  await signInWithEmailAndPassword(auth, 'test@gmail.com', 'password');
};
const logout = async () => {
  await signOut(auth);
};

const ReactQueryFirebaseSample = () => {
  const { data: user, isLoading, error } = useAuthUser(['user'], auth);

  return (
    <div>
      <p>
        {error && <strong>Error: {error}</strong>}
        {isLoading && <span>Collection: Loading...</span>}
      </p>
      {user && (
        <div>
          <p>Current User: {user.email}</p>
          <button onClick={logout}>Logout</button>
        </div>
      )}
      <button onClick={login}>Login</button>
    </div>
  );
};
```

# 比較・考察
コード量, SDKへの依存度ともにほぼ等しいと言える結果になりました。
これらの結果からでは, 両者に大きな差はないためどちらを使っても変わらないと思われます。
しかし, React-Query-Firebaseについてみると, クエリを投げる関数の引数にクエリキーをしていることがわかります。ここで, 公式のREADMEから抜粋した一文について見てみます。 

> Data fetching is handled via Queries and Query Keys, meaning components can share > data throughout your application without needless database reads. (データの取得は、クエリとクエリキーで処理されます。つまり、コンポーネントは、不必要なデータベース読み取りをすることなく、アプリケーション全体でデータを共有することができます。)  

このようにReact-Query-Firebaseでは必要なデータのみに焦点を絞ってデータを取得するので, パフォーマンス向上を狙えるのではないかなと思います。

# 感想
ここまで読んでくださった方は結局どっちが良いのかと思われるかもしれませんが, 個人的にはReact-Query-Firebaseに軍配が上がるのではないかと思います。
理由としては, 上記で挙げたパフォーマンスの観点以外にも, 以下のような**強み**があります。 

- React-Query-Firebaseは`React Query`上に構築されているため, React Queryの旨味も持っている
- ユーザーのサインイン、ドキュメントの削除、トランザクションの実行、イベントの記録などの処理を`Mutation`を介して行うことで複雑なローカルローディングやエラーステートの管理などに手間をとられずにアプリケーションに集中することができる。

もう一方のReact-Firebase-Hooksについては, `記述量が少なくなる`という点以外に**強み**が見当たリませんでした。(気付いてないだけかもしれませんが)

# 参考
https://github.com/CSFrequency/react-firebase-hooks/tree/v4.0.2
https://github.com/invertase/react-query-firebase
https://react-query-firebase.invertase.dev/