概要
Next.js で reactfireを使ってfirestoreを操作する方法
前提
- next 13.0.6
- react 18.2.0
- firebase 9.15.0
- reactfire 4.2.2
使い方
ポイントは、firebaseを利用するために、FirebaseAppProviderを使って、firebase appを生成するのと、FirebaseAppProviderで生成したfirebase appからfirestoreを生成するところ。authなどの生成もFirebaseSDKProviders
で行えばいい。
firestore SDKを提供するコンポーネントを作成する
このあたりが直観的でないのですが、FirebaseAppProviderでいろいろ用意しておいてほしいところですが、FirestoreProvider
を使ってsdkにfirestoreのインスタンスを渡す必要があります。
pages/firebase-provider.tsx
import {FirestoreProvider, useFirebaseApp} from 'reactfire';
import {getFirestore} from 'firebase/firestore';
export default function FirebaseSDKProviders({children}: any) {
const app = useFirebaseApp();
const firestore = getFirestore(app);
return <FirestoreProvider sdk={firestore}>{children}</FirestoreProvider>;
}
AppのComponentの親にFirebaseAppProvider等を追加する
FirebaseAppProvider
と上で作成したFirebaseSDKProviders
をComponent
の親に指定します
firebaseConfig
はfirebaseの管理画面からウェブアプリを作ったときに出てくるスニペットを貼り付けてます
pages/_app.tsx
import '../styles/globals.css'
import type {AppProps} from 'next/app'
import {FirebaseAppProvider} from "reactfire";
import FirebaseSDKProviders from "./firebase-provider";
// Your web app's Firebase configuration
const firebaseConfig = {
apiKey: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
authDomain: "xxxxxxxxxx.firebaseapp.com",
projectId: "xxxxxxxxxx",
storageBucket: "xxxxxxxxxx.appspot.com",
messagingSenderId: "999999999999",
appId: "1:999999999999:web:xxxxxxxxxxxxx"
};
export default function App({Component, pageProps}: AppProps) {
return <FirebaseAppProvider firebaseConfig={firebaseConfig}>
<FirebaseSDKProviders>
<Component {...pageProps} />
</FirebaseSDKProviders>
</FirebaseAppProvider>
}
利用する
長ったらしく書きましたが、大事なのは、useFirestore
でfirestoreのインスタンスが利用できるところかと思います。あとは普通です。
pages/todo/index.tsx
import React, {useState} from "react";
import {addDoc, collection,} from 'firebase/firestore';
import {useFirestore, useFirestoreCollectionData} from 'reactfire';
export default function Todo() {
const [text, setText] = useState("");
const firestore = useFirestore();
const todo = collection(firestore, 'todo');
const {status, data} = useFirestoreCollectionData(todo);
const addTodo = async () => {
await addDoc(todo, {todo: text})
setText("")
}
if (status === 'loading') {
return <p>Fetching todo list...</p>;
}
//console.log(data)
return (
<>
<div>
<input type="text" value={text} onChange={(event) => setText(event.target.value)}/>
<button type="button" onClick={() => addTodo()}>add</button>
</div>
{data.map((d) => (
<p key={d.NO_ID_FIELD}>{d.todo}</p>
))}
</>
);
};
付録
プロジェクトの作成
% yarn create next-app
% firebase init
% yarn add firebase reactfire