💛
Firestoreを使っていいね機能を実装する
よくある機能をつけたい
SNSアプリを作っていて、like数をカウントするいいね機能を実装することがありますよね。
どうやってつければいいのか?
List型のデータで保存する必要があって、[]
の中に、["id1","id2","id3"]
といった感じのデータ構造が必要です。以下のようなコレクションを作れば実現できます!
いいね機能を実装する
いいねは、一回しかつけれないので、1回だけリストにデータを増やすメソッドと、データがあったら削除するメソッドを実装します。
公式ドキュメントによると、この機能で実現できます。
final washingtonRef = db.collection("cities").doc("DC");
// Atomically add a new region to the "regions" array field.
washingtonRef.update({
"regions": FieldValue.arrayUnion(["greater_virginia"]),
});
// Atomically remove a region from the "regions" array field.
washingtonRef.update({
"regions": FieldValue.arrayRemove(["east_coast"]),
});
公式を参考に考えた機能だと、今回はハードコーディングですけど、ドキュメントIDをリストに保存して、それをカウントして、何人にいいねされているかをカウントする機能を実装しました!
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
final blogProvider = StreamProvider((ref) async* {
final db = FirebaseFirestore.instance;
final snapshots = db.collection('blog').snapshots();
yield* snapshots.map((snapshot) => snapshot.docs.map((doc) => doc.data()));
});
class LikePage extends HookConsumerWidget {
const LikePage({Key? key}) : super(key: key);
Widget build(BuildContext context, WidgetRef ref) {
final blogAsyncValue = ref.watch(blogProvider);
return Scaffold(
appBar: AppBar(title: const Text('LikePage')),
body: blogAsyncValue.when(
data: (blogs) {
return ListView(
children: blogs.map((blog) {
return ListTile(
trailing: IconButton(
onPressed: () async {
// likesフィールドにいいねをつける。いいねをつけるときは、idをつける
// 今回はもうしわけないけど、ハードコーディングでidをつけています🙇
var id = 'erafFz7Vopqfdx4C6dKV';
final db = FirebaseFirestore.instance;
final doc = db.collection('blog').doc(id);
// if文でlikesをつけていなかったら、つける。なかったら外す
if (blog['likes'].contains(id)) {
await doc.update({
'likes': FieldValue.arrayRemove([id])
});
} else {
await doc.update({
'likes': FieldValue.arrayUnion([id])
});
}
},
icon: const Icon(Icons.favorite)),
subtitle: Row(
children: [
// trueだったら、赤色のアイコンを表示。falseだったら、グレーのアイコンを表示。三項演算子を使う
blog['likes'].contains('erafFz7Vopqfdx4C6dKV')
? const Icon(Icons.favorite, color: Colors.red)
: const Icon(Icons.favorite, color: Colors.grey),
const SizedBox(width: 8),
Text(blog['likes'].length.toString()),
],
),
// arrayのlikesの長さを表示
title: Text(blog['title']),
);
}).toList(),
);
},
error: (error, stackTrace) => Text('Error: $error'),
loading: () => const Center(child: CircularProgressIndicator()),
),
);
}
}
こちらのコードで、importして実行するだけ。
main.dart
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:widget_cook/firebase_options.dart';
import 'package:widget_cook/liks/like_page.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
runApp(const ProviderScope(child: BlogApp()));
}
class BlogApp extends StatelessWidget {
const BlogApp({Key? key}) : super(key: key);
Widget build(BuildContext context) {
return MaterialApp(
title: 'BlogApp',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const LikePage(),
);
}
}
gif画像用意しました
最後に
今回、ざっくりとですがFirestoreに、 like数を保存と取り消しをする機能を実装してみました。海外の情報しか技術記事ない気がして、書いてみました。参考になりそうでしたら、使ってみてください。
Discussion