React Native ExpoでFirestore+unstatedを使って更新機能を作る
前提としてデータの追加・削除・更新はreferenceに対して行います。
そのため、更新する際はまずドキュメントIDからdocumentReferenceを取得する必要があります。
扱うデータモデルを確認
以下のような投稿データを管理するデータモデルを想定しています。
idはFirestoreのドキュメントIDが入っています。
export type Post = {
id: string,
name: string,
description: string,
photo: string,
likeCount: number,
}
Firebaseの共通クラスにupdate処理を実装する
React Native ExpoでFirebaseを使う場合は処理をまとめておくと便利です。
ここではutils/Fire.ts
という共通ファイルを追加しています。
documentReferenceに対してupdateする
前提としてFirestoreでデータを追加・削除・更新する場合は、Referenceに対して行います。
そのためpostsコレクションから一度ドキュメントIDでdocumentReferenceを取得してから、
受け取ったデータで更新を行っています。
//utils/Fire.ts
updatePost = async (post: Post) => {
const postDocumentReference = this.db.collection('posts').doc(post.id)
await postDocumentReference.update({
name: post.name,
description: post.description,
photo: post.photo,
likeCount: post.likeCount,
})
}
非同期処理はunstatedのContainer内に書く
unstatedのContainerとは、
Reduxでいう所の「Action+Reducer+Middleware+Store」みたいなイメージです。
管理している対象のグローバルなstateに対する取得や変更の処理を、
全て一箇所にできるのでReduxに比べるとスッキリと書くことが出来ます。
unstatedのContainer内に実装する例
Container内でまずFirestoreの更新処理を実行してから、stateを更新するようにします。
本来はFirebase側のエラーハンドリングが必要ですが、ここでは省いています。
updatePost = async (post: Post) => {
const {
posts
} = this.state
// Firebase更新処理
await Fire.shared.updatePost(post)
let newPosts: Array<Post> = [...posts]
let newPost: Post = newPosts[postIndex]
newPost.name = post.name
newPost.description = post.description
newPost.photo = post.photo
newPosts[postIndex] = newPost
this.setState({ posts: newPosts })
}
React Native Debuggerでデバッグする
上手く更新ができない場合はReact Native Debuggerのログを見ましょう。
自分の場合は最初動かなったのですが、ビュー側でlikeCountを渡すのを忘れていたため、
undefinedの値が弾かれていたのが原因でした。
おわりに
今日書いたコードはGithubに上げているので、全文を見たい方は参考にしてみてください。
もしよければスターもつけていただけると嬉しいです。
参考にした資料
Discussion