はじめに
前回の記事では、react-firebase-hooksを試したのですが、12月6日のReact Day Berlinでは、ReactFireのプレゼンがありました。こちらはとても先進的で期待できます。
本記事では、Firestoreの部分を移植してみたいと思います。
ReactFireとは
ReactFire v1は2016年5月のリリースを最後に、その後deprecateされ、Firebase JS SDKを直接使うようアナウンスされています。それが2019年7月よりv2として再度開発しているようです。
https://github.com/FirebaseExtended/reactfire
現在、masterブランチがv2になっています。
READMEには、
Status: Alpha. ReactFire is meant for React Concurrent Mode, which is only available in experimental React builds.
と書いてあるのですが、ざっとコードを見たところ、Suspenseを使っているだけで、Concurrent Modeでなくても動きそうです。
コーディング
import React, { Suspense, useState } from "react";
import ReactDOM from "react-dom";
import "firebase/firestore";
import {
FirebaseAppProvider,
useFirestoreCollectionData,
useFirestore
} from "reactfire";
const firebaseConfig = {
apiKey: "...",
authDomain: "...",
databaseURL: "...",
projectId: "...",
storageBucket: "...",
messagingSenderId: "...",
appId: "..."
};
const TodoList = () => {
const firestore = useFirestore();
const todosRef = firestore().collection("todos");
const values = useFirestoreCollectionData(todosRef, { idField: "id" });
return (
<ul>
{values.map(value => (
<li key={value.id}>{value.title}</li>
))}
</ul>
);
};
const NewTodo = () => {
const [title, setTitle] = useState("");
const [pending, setPending] = useState(false);
const firestore = useFirestore();
const add = async () => {
setTitle("");
setPending(true);
try {
await 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>
);
};
const App = () => {
return (
<FirebaseAppProvider firebaseConfig={firebaseConfig}>
<Suspense fallback={<div>Loading...</div>}>
<div>
<TodoList />
<NewTodo />
</div>
</Suspense>
</FirebaseAppProvider>
);
};
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
動きました。nextではだめで、canaryを使う必要がありました。
おわりに
ドキュメントがまだ追いついていなくて、ソースコードを読まないといけなかったです。