React.js & Next.jsの勉強メモ

概要

React.js & Next.js超入門 第2版 を読んでちまちま写経していたが、 firebaseのところが現行のversion9とは結構乖離が大きくなっていたので、差分をメモしておく。 (買ってから1年以上放置してたのがそもそも悪い)

差分

初期化

書籍内

import firebase from 'firebase'

const firebaseConfig = {..}
if ( firebase.apps.length == 0) {
  firebase.initializeApp(firebaseConfig)
}

現行

import { initializeApp } from 'firebase/app';

const firebaseConfig = {...}
const app = initializeApp(firebaseConfig);
export default app;

firestoreオブジェクトの取得

書籍内

import firebase from 'firebase'

const db = firebase.firestore()

現行

import { getFirestore } from 'firebase/firestore';

const db = getFirestore(app)

ドキュメントの取得(複数)

書籍内

db.collection('mydata').get().then((snapshot) => {
  snapshot.forEach((document) => {
    const doc = document.data()
    ...
  })
})

現行

import { getFirestore, collection, getDocs } from 'firebase/firestore';

const cols = collection(db, 'mydata')
getDocs(cols).then((snapshot) => {
  snapshot.forEach((document) => {
    const doc = document.data()
    ...
  })
})

ドキュメントの取得(単一)

書籍内

import firebase from 'firebase'
import { useRouter } from 'next/router'

const router = useRouter()

if ( router.query.id != undefined ) {
  db.collection('mydata').doc(router.query.id).get().then(ob => {
    const data = ob.data()
    ...
  })
}

現行

import { getFirestore, collection, doc, getDoc } from 'firebase/firestore'
import { useRouter } from 'next/router'

const router = useRouter()

if ( router.isReady && router.query.id !== undefined ) {
  const docRef = doc(db, 'mydata', router.query.id)
  getDoc(docRef).then(ob => {
    const data = ob.data()
    ...
  })
}

追加

書籍内

import firebase from 'firebase'

const db = {
  name: name,
  mail: mail,
  age: age
}

db.collection('mydata').add(ob).then(ref => {
  ...
})

現行

import { getFirestore, collection, addDoc } from "firebase/firestore"

const ob = {
  name: name,
  mail: mail,
  age: age
}

addDoc(collection(db, 'mydata'), ob).then(ref => {
  router.push('/fire')
})

削除

書籍内

import firebase from 'firebase'
import { useRouter } from 'next/router'

const router = useRouter()

db.collection('mydata').doc(router.query.id)
  .delete().then(ref => {
    ...
  })

現行

import { getFirestore, doc, getDoc } from 'firebase/firestore'
import { useRouter } from 'next/router'

const router = useRouter()

const docRef = doc(db, 'mydata', router.query.id)
deleteDoc(docRef).then(ref => {
  ...
})

検索

書籍内

import firebase from 'firebase'

// 検索対象の文字列
const name = '...'

// 完全一致
db.collection('mydata').where('name', '==', name).get()
  .then(snapshot => {
    snapshot.forEach((document) => {
      ...
    })
  })

// 前方一致
db.collection('mydata').orderBy('name').startAt(name).endAt(name + "\uf8ff")
  .then(snapshot => {
    snapshot.forEach((document) => {
      ...
    })
  })

現行

import { getFirestore, collection, query, where, orderBy, startAt, endAt, getDocs } from 'firebase/firestore/lite';

// 検索対象の文字列
const name = '...'

// 完全一致
const cols = collection(db, 'mydata')
const q = query(cols, where('name', '==', name))
getDocs(q).then(snapshot => {
  snapshot.forEach(document => {
    ...
  })
})


// 前方一致
const cols = collection(db, 'mydata')
const q = query(cols, orderBy('name'), startAt(name), endAt(name + "\uf8ff"))
getDocs(q).then(snapshot => {
  snapshot.forEach(document => {
    ...
  })
})

ちなみに startAt(name) endAt(name + "\uf8ff") は範囲指定を意味している。 \uf8ff はコードポイントの最大値であり、上記はnameに続く文字が 0x0000〜0xf8ff の範囲にあることを示している。 例えば name: hoge のとき、

  • 先頭4文字が hoge に一致し、
  • 5文字目が 0x0000〜0xf8ff の範囲にある、つまり終端や全ての文字に一致する

という条件になるらしい。