🐷
React + RxDB:3つのアプローチを徹底比較
RxDBをReactアプリで使う際、実は3つの選択肢があります。それぞれの特徴と使い分けを、コード例とともに解説します。
はじめに
RxDBは強力なオフラインファースト対応のデータベースですが、Reactとの統合方法には複数のアプローチが存在します。本記事では、以下の3つの方法を比較します:
- RxDB単体 - 手動でサブスクリプション管理
- rxdb-hooks - React専用の軽量フック
- TanStack DB - TanStackエコシステム統合
アプローチ1:RxDB単体(手動サブスクリプション)
最もシンプルですが、ボイラープレートが多くなります。
import { useEffect, useState } from 'react'
function TodoList({ rxDatabase }) {
const [todos, setTodos] = useState([])
const [loading, setLoading] = useState(true)
// 手動でサブスクリプション管理が必要
useEffect(() => {
const subscription = rxDatabase.todos
.find()
.$ // RxDB Observable
.subscribe(documents => {
setTodos(documents)
setLoading(false)
})
// クリーンアップも忘れずに
return () => subscription.unsubscribe()
}, [rxDatabase])
const addTodo = async (text) => {
await rxDatabase.todos.insert({
id: crypto.randomUUID(),
text,
completed: false
})
}
const toggleTodo = async (id) => {
const doc = await rxDatabase.todos.findOne(id).exec()
await doc.patch({ completed: !doc.completed })
}
if (loading) return 読み込み中...
return (
{todos.map(todo => (
<input
type="checkbox"
checked={todo.completed}
onChange={() => toggleTodo(todo.id)}
/>
{todo.text}
))}
<button onClick={() => addTodo('新しいTodo')}>追加
)
}
メリット
- 依存関係が少ない
- RxDBの機能を直接使える
- シンプルなアプリには十分
デメリット
-
useState+useEffectのボイラープレートが多い - サブスクリプション管理を手動で行う必要がある
- コンポーネントごとに同じパターンを繰り返す
アプローチ2:rxdb-hooks(推奨!)
React + RxDB専用に設計された軽量ライブラリです。
import { useRxQuery, useRxDB } from 'rxdb-hooks'
function TodoList() {
const db = useRxDB()
// たった1行でリアクティブなクエリ!
const { result: todos, isFetching } = useRxQuery(
db.todos.find()
)
const addTodo = async (text) => {
await db.todos.insert({
id: crypto.randomUUID(),
text,
completed: false
})
// 自動的にUIが更新される
}
const toggleTodo = async (id) => {
const doc = await db.todos.findOne(id).exec()
await doc.patch({ completed: !doc.completed })
}
if (isFetching) return 読み込み中...
return (
{todos?.map(todo => (
<input
type="checkbox"
checked={todo.completed}
onChange={() => toggleTodo(todo.id)}
/>
{todo.text}
))}
<button onClick={() => addTodo('新しいTodo')}>追加
)
}
セットアップ
import { RxDBProvider } from 'rxdb-hooks'
function App() {
return (
)
}
メリット
- ✅ ボイラープレートがほぼゼロ
- ✅ RxDBに特化した設計で使いやすい
- ✅ 軽量(RxDB専用なので余計な機能がない)
- ✅ RxDBのクエリをそのまま使える
- ✅ 自動的にサブスクリプション管理
- ✅ ローディング状態を自動で管理
デメリット
- React専用(Vue、Svelteなどでは使えない)
アプローチ3:TanStack DB
TanStackエコシステムとの統合を提供します。
import { createCollection, useQuery } from '@tanstack/react-db'
import { rxdbCollectionOptions } from '@tanstack/rxdb-db-collection'
// セットアップ(コンポーネント外で1回だけ)
const todosCollection = createCollection(
rxdbCollectionOptions({
rxCollection: myDatabase.todos,
startSync: true
})
)
function TodoList() {
// TanStack Queryのような使用感
const { data: todos = [], isLoading } = useQuery({
queryKey: ['todos'],
queryFn: () => todosCollection.getAll()
})
const addTodo = async (text) => {
await todosCollection.insert({
id: crypto.randomUUID(),
text,
completed: false
})
}
const toggleTodo = async (id) => {
const todo = todosCollection.getById(id)
await todosCollection.update(id, {
completed: !todo.completed
})
}
if (isLoading) return 読み込み中...
return (
{todos.map(todo => (
<input
type="checkbox"
checked={todo.completed}
onChange={() => toggleTodo(todo.id)}
/>
{todo.text}
))}
<button onClick={() => addTodo('新しいTodo')}>追加
)
}
メリット
- ✅ TanStack Query、Router等との統合がスムーズ
- ✅ React、Vue、Solid、Svelteなど複数フレームワーク対応
- ✅ TanStack Queryの高度なキャッシング戦略を活用
- ✅ 統一されたAPIで学習コストが低い
デメリット
- RxDBだけのために導入するには重い
- rxdb-hooksに比べて抽象化レイヤーが増える
- RxDBの機能を直接使うには追加の設定が必要
バックエンド同期について
重要なポイント:どのアプローチでもRxDBの同期機能は独立して動作します。
import { replicateRxCollection } from 'rxdb/plugins/replication'
// RxDBで同期設定(どのアプローチでも同じ)
const replicationState = replicateRxCollection({
collection: db.todos,
pull: {
handler: async (checkpoint, batchSize) => {
const response = await fetch('/api/todos/pull', {
method: 'POST',
body: JSON.stringify({ checkpoint, batchSize })
})
return response.json()
}
},
push: {
handler: async (docs) => {
await fetch('/api/todos/push', {
method: 'POST',
body: JSON.stringify({ docs })
})
}
}
})
rxdb-hooks または TanStack DB を使う場合:
- RxDBで同期が実行されると、変更は自動的にUIに反映される
- 追加のコードは不要
- リアクティブなフックが変更を検知して自動で再レンダリング
RxDB単体 の場合:
- サブスクリプションを適切に設定していれば同じように動作
- ただし、各コンポーネントで手動管理が必要
比較表
| 項目 | RxDB単体 | rxdb-hooks | TanStack DB |
|---|---|---|---|
| ボイラープレート | 多い | 少ない | 少ない |
| 学習コスト | 低 | 低 | 中(TanStack知識が必要) |
| 依存関係 | 最小 | 小 | 大 |
| フレームワーク対応 | 手動実装次第 | React専用 | 複数対応 |
| RxDB統合 | 直接 | 最適化済み | 抽象化レイヤー経由 |
| パフォーマンス | 高 | 高 | 高 |
| おすすめ度 | ⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ |
どれを選ぶべきか?
rxdb-hooksを選ぶべき場合(大多数)
- ✅ Reactアプリを開発している
- ✅ RxDBを最大限活用したい
- ✅ シンプルで軽量なソリューションが欲しい
- ✅ RxDBのクエリAPIに慣れている
TanStack DBを選ぶべき場合
- ✅ 既にTanStack Query、Routerなどを使っている
- ✅ 複数フレームワーク対応のライブラリを作っている
- ✅ TanStackエコシステムで統一したい
- ✅ TanStack Queryのキャッシング戦略が必要
RxDB単体を使うべき場合
- ✅ 非常にシンプルなアプリ
- ✅ 依存関係を最小限にしたい
- ✅ カスタマイズが必要
結論
ほとんどのReact + RxDBプロジェクトには、rxdb-hooksがベストチョイスです。
理由:
- RxDB専用に設計されているため、APIが自然
- 軽量で追加のオーバーヘッドがほぼない
- RxDBの全機能を直接使える
- ボイラープレートが最小限
TanStack DBは素晴らしいライブラリですが、既にrxdb-hooksで解決されている問題に対して、より重厚なソリューションを提供しているという印象です。TanStackエコシステムに深く依存している場合や、マルチフレームワーク対応が必要な場合にのみ、TanStack DBを検討すると良いでしょう。
インストール
# rxdb-hooksを使う場合(推奨)
npm install rxdb rxdb-hooks
# TanStack DBを使う場合
npm install rxdb @tanstack/react-db @tanstack/rxdb-db-collection
参考リンク
この記事が、RxDBとReactの統合方法選びの参考になれば幸いです!
Discussion