- 参考
https://www.flutter-study.dev/firebase/cloud-firestore-try
https://zenn.dev/maropook/articles/f82c98a56b14ca
https://note.com/hatchoutschool/n/na654d6dc5a53
pubspec.yaml
dependencies: flutter: sdk: flutter cupertino_icons: ^1.0.2 firebase_core: ^1.0.1 cloud_firestore: ^3.1.13 cloud_firestore_web: ^2.6.13
dependenciesに firebase_core: ^1.0.1 cloud_firestore: ^3.1.13 cloud_firestore_web: ^2.6.13 を追加する
index.html
<!DOCTYPE html> <html> <head> (略) </head> <body> <script type="module"> // Import the functions you need from the SDKs you need import { initializeApp } from "https://www.gstatic.com/firebasejs/9.8.3/firebase-app.js"; import { getAnalytics } from "https://www.gstatic.com/firebasejs/9.8.3/firebase-analytics.js"; // TODO: Add SDKs for Firebase products that you want to use // https://firebase.google.com/docs/web/setup#available-libraries // Your web app's Firebase configuration // For Firebase JS SDK v7.20.0 and later, measurementId is optional const firebaseConfig = { apiKey: "AIzaSyDd55SAcL-qBGe0iidvrEelD0Lxd2FJbBo", authDomain: "myapp-47093.firebaseapp.com", projectId: "myapp-47093", storageBucket: "myapp-47093.appspot.com", messagingSenderId: "202117038660", appId: "1:202117038660:web:6fecd6df4a33756b63b211", measurementId: "G-D4MXME2D3W" }; // Initialize Firebase const app = initializeApp(firebaseConfig); const analytics = getAnalytics(app); </script> <script src="main.dart.js" type="application/javascript"></script> </body> </html>
<body>~</body>に<script type="module">~</script>を追加する 末尾に<script src="main.dart.js" type="application/javascript"></script>を追加する
main.dart
import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:flutter/material.dart'; main() { Firebase.initializeApp( options: const FirebaseOptions( apiKey: "AIzaSyDd55SAcL-qBGe0iidvrEelD0Lxd2FJbBo", appId: "myapp-47093.firebaseapp.com", messagingSenderId: "202117038660", projectId: "myapp-47093", ) ); runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) => MaterialApp( debugShowCheckedModeBanner: false, title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, visualDensity: VisualDensity.adaptivePlatformDensity, ), home: const MyFirestorePage(), ); } class MyFirestorePage extends StatefulWidget { const MyFirestorePage({Key? key}) : super(key: key); @override State<StatefulWidget> createState() => _MyFirestorePageState(); } class _MyFirestorePageState extends State<MyFirestorePage> { List<DocumentSnapshot> users = []; List<String> nekoItems = []; @override Widget build(BuildContext context) => Scaffold( body: Center( child: Column( children: <Widget>[ Container( margin: const EdgeInsets.all(8), child: ElevatedButton( child: const Text('ユーザー neko ushi 登録'), onPressed: () { FirebaseFirestore.instance.collection('users').doc(1.toString()).set({'name': 'neko', 'age': 100}); FirebaseFirestore.instance.collection('users').doc(2.toString()).set({'name': 'ushi', 'age': 1333}); }, ) ), Container( margin: const EdgeInsets.all(8), child: ElevatedButton( child: const Text('item 購入 (neko)'), onPressed: () { FirebaseFirestore.instance.collection('users').doc(1.toString()).collection('items').doc(1.toString()).set({'name': 'cake', 'price': 600, 'date': '09/13'}); FirebaseFirestore.instance.collection('users').doc(1.toString()).collection('items').doc(2.toString()).set({'name': 'nasu', 'price': 999, 'date': '12/25'}); }, ), ), Container( margin: const EdgeInsets.all(8), child: ElevatedButton( child: const Text('全ユーザー表示'), onPressed: () async { // ユーザーを取得してUIに反映 final ss = await FirebaseFirestore.instance.collection('users').get(); setState( (){ users = ss.docs; } ); }, ), ), Column( children: [ for (var e in users) ... { Text('${e['name']}さん'), Text('${e['age']}歳'), } ], ), ElevatedButton( child: const Text('nekoさんの購入物を表示'), onPressed: () async { // 購入物を取得してUIに反映 for (int i = 1; i < 3; i++) { final ss = await FirebaseFirestore.instance.collection('users').doc('1').collection('items').doc(i.toString()).get(); setState( () { nekoItems.add('${ss['name']} ${ss['price']}円 ${ss['date']}'); } ); } }, ), Column( children: [ for (var e in nekoItems) ... { Text(e) } ], ), ], ), ), ); }
エラー "FirebaseOptions cannot be null when creating the default app." の対処 → Firebase.initializeApp() に初期値を与えることで解決 StatelessWidget に StatefulWidget を載せていくのが定跡らしい StatelessWidget はインターフェースで Widget build (BuildContext context) => MaterialApp () を定義しなければならない StatefulWidget はインターフェースで State<StatefulWidget> createState () => nyaa; を定義しなければならない List<String> nekoItems = []; Dart界隈は変数を lowerCamelCase で書くのが推奨らしい final ss = await FirebaseFirestore.instance.collection('users').get(); コレクションに対してgetを呼ぶと ss は query snap shot 型になる setState( (){ users = ss.docs; } ); UIに反映させる変数はsetState内で更新する query snap shot 型はメンバ docs を使うと list<DocumentSnapShot> に変換できる for (var e in users) ... { Text('${e['name']}さん'), Text('${e['age']}歳'), } children 内で for を使うには ... を書く必要がある final ss = await FirebaseFirestore.instance.collection('users').doc('1').collection('items').doc(i.toString()).get(); ドキュメントIDを指定してgetを呼ぶと ss は document snap shot 型になる setState( () { nekoItems.add('${ss['name']} ${ss['price']}円 ${ss['date']}'); } ); document snap shot 型は map 型 欠点: 単純なデザインでもネストが深いのが気になる