-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathfirebase.html
1194 lines (1106 loc) · 147 KB
/
firebase.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE html>
<html lang="en" xml:lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>Chapter 19 Firebase | Client-Side Web Development</title>
<meta name="description" content="The course reader for INFO 340: Client-Side Web Development." />
<meta name="generator" content="bookdown 0.24 and GitBook 2.6.7" />
<meta property="og:title" content="Chapter 19 Firebase | Client-Side Web Development" />
<meta property="og:type" content="book" />
<meta property="og:url" content="https://info340.github.io/" />
<meta property="og:image" content="https://info340.github.io//img/cover-img.png" />
<meta property="og:description" content="The course reader for INFO 340: Client-Side Web Development." />
<meta name="github-repo" content="info340/book" />
<meta name="twitter:card" content="summary" />
<meta name="twitter:title" content="Chapter 19 Firebase | Client-Side Web Development" />
<meta name="twitter:description" content="The course reader for INFO 340: Client-Side Web Development." />
<meta name="twitter:image" content="https://info340.github.io//img/cover-img.png" />
<meta name="author" content="Joel Ross" />
<meta name="date" content="2025-01-16" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
<link rel="shortcut icon" href="img/busy-spider-icon.png" type="image/x-icon" />
<link rel="prev" href="ajax.html"/>
<link rel="next" href="code-style-guide.html"/>
<script src="libs/header-attrs-2.11/header-attrs.js"></script>
<script src="libs/jquery-3.6.0/jquery-3.6.0.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/fuse.min.js"></script>
<link href="libs/gitbook-2.6.7/css/style.css" rel="stylesheet" />
<link href="libs/gitbook-2.6.7/css/plugin-table.css" rel="stylesheet" />
<link href="libs/gitbook-2.6.7/css/plugin-bookdown.css" rel="stylesheet" />
<link href="libs/gitbook-2.6.7/css/plugin-highlight.css" rel="stylesheet" />
<link href="libs/gitbook-2.6.7/css/plugin-search.css" rel="stylesheet" />
<link href="libs/gitbook-2.6.7/css/plugin-fontsettings.css" rel="stylesheet" />
<link href="libs/gitbook-2.6.7/css/plugin-clipboard.css" rel="stylesheet" />
<link href="libs/anchor-sections-1.0.1/anchor-sections.css" rel="stylesheet" />
<script src="libs/anchor-sections-1.0.1/anchor-sections.js"></script>
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-98444716-3', 'auto');
ga('send', 'pageview');
</script>
<link rel="stylesheet" href="css/style.css" type="text/css" />
<link rel="stylesheet" href="css/prism.min.css" type="text/css" />
</head>
<body>
<div class="book without-animation with-summary font-size-2 font-family-1" data-basepath=".">
<div class="book-summary">
<nav role="navigation">
<ul class="summary">
<li><a href="./" class="title">Client-Side Web Development</a></li>
<li class="divider"></li>
<li class="chapter" data-level="" data-path="index.html"><a href="index.html"><i class="fa fa-check"></i>About the Book</a></li>
<li class="chapter" data-level="1" data-path="software-setup.html"><a href="software-setup.html"><i class="fa fa-check"></i><b>1</b> Getting Setup</a>
<ul>
<li class="chapter" data-level="1.1" data-path="software-setup.html"><a href="software-setup.html#web-browser"><i class="fa fa-check"></i><b>1.1</b> Web Browser</a></li>
<li class="chapter" data-level="1.2" data-path="software-setup.html"><a href="software-setup.html#code-editor"><i class="fa fa-check"></i><b>1.2</b> Code Editor</a>
<ul>
<li class="chapter" data-level="" data-path="software-setup.html"><a href="software-setup.html#visual-studio-code"><i class="fa fa-check"></i>Visual Studio Code</a></li>
<li class="chapter" data-level="1.2.1" data-path="software-setup.html"><a href="software-setup.html#other-editors"><i class="fa fa-check"></i><b>1.2.1</b> Other Editors</a></li>
</ul></li>
<li class="chapter" data-level="1.3" data-path="software-setup.html"><a href="software-setup.html#bash-command-line"><i class="fa fa-check"></i><b>1.3</b> Bash (Command Line)</a></li>
<li class="chapter" data-level="1.4" data-path="software-setup.html"><a href="software-setup.html#node-and-npm"><i class="fa fa-check"></i><b>1.4</b> Node and <code>npm</code></a>
<ul>
<li class="chapter" data-level="" data-path="software-setup.html"><a href="software-setup.html#installing-software-with-npm"><i class="fa fa-check"></i>Installing software with npm</a></li>
<li class="chapter" data-level="" data-path="software-setup.html"><a href="software-setup.html#managing-local-packages"><i class="fa fa-check"></i>Managing local packages</a></li>
</ul></li>
<li class="chapter" data-level="1.5" data-path="software-setup.html"><a href="software-setup.html#git-and-github"><i class="fa fa-check"></i><b>1.5</b> Git and GitHub</a></li>
<li class="chapter" data-level="" data-path="software-setup.html"><a href="software-setup.html#resources"><i class="fa fa-check"></i>Resources</a></li>
</ul></li>
<li class="chapter" data-level="2" data-path="client-side-development.html"><a href="client-side-development.html"><i class="fa fa-check"></i><b>2</b> Client-Side Development</a>
<ul>
<li class="chapter" data-level="2.1" data-path="client-side-development.html"><a href="client-side-development.html#clients-and-servers"><i class="fa fa-check"></i><b>2.1</b> Clients and Servers</a></li>
<li class="chapter" data-level="2.2" data-path="client-side-development.html"><a href="client-side-development.html#urls-and-web-files"><i class="fa fa-check"></i><b>2.2</b> URLs and Web Files</a>
<ul>
<li class="chapter" data-level="" data-path="client-side-development.html"><a href="client-side-development.html#client-side-file-types"><i class="fa fa-check"></i>Client-Side File Types</a></li>
</ul></li>
<li class="chapter" data-level="2.3" data-path="client-side-development.html"><a href="client-side-development.html#servers-and-hosting"><i class="fa fa-check"></i><b>2.3</b> Servers and Hosting</a>
<ul>
<li class="chapter" data-level="" data-path="client-side-development.html"><a href="client-side-development.html#hosting-with-github-pages"><i class="fa fa-check"></i>Hosting with GitHub Pages</a></li>
<li class="chapter" data-level="" data-path="client-side-development.html"><a href="client-side-development.html#development-servers"><i class="fa fa-check"></i>Development Servers</a></li>
</ul></li>
<li class="chapter" data-level="2.4" data-path="client-side-development.html"><a href="client-side-development.html#web-standards"><i class="fa fa-check"></i><b>2.4</b> Web Standards</a></li>
<li class="chapter" data-level="2.5" data-path="client-side-development.html"><a href="client-side-development.html#web-accessibility"><i class="fa fa-check"></i><b>2.5</b> Web Accessibility</a>
<ul>
<li class="chapter" data-level="" data-path="client-side-development.html"><a href="client-side-development.html#supporting-accessibility"><i class="fa fa-check"></i>Supporting Accessibility</a></li>
</ul></li>
</ul></li>
<li class="chapter" data-level="3" data-path="html-fundamentals.html"><a href="html-fundamentals.html"><i class="fa fa-check"></i><b>3</b> HTML Fundamentals</a>
<ul>
<li class="chapter" data-level="3.1" data-path="html-fundamentals.html"><a href="html-fundamentals.html#html-elements"><i class="fa fa-check"></i><b>3.1</b> HTML Elements</a>
<ul>
<li class="chapter" data-level="" data-path="html-fundamentals.html"><a href="html-fundamentals.html#some-example-elements"><i class="fa fa-check"></i>Some Example Elements</a></li>
<li class="chapter" data-level="" data-path="html-fundamentals.html"><a href="html-fundamentals.html#comments"><i class="fa fa-check"></i>Comments</a></li>
<li class="chapter" data-level="" data-path="html-fundamentals.html"><a href="html-fundamentals.html#attributes"><i class="fa fa-check"></i>Attributes</a></li>
<li class="chapter" data-level="" data-path="html-fundamentals.html"><a href="html-fundamentals.html#empty-elements"><i class="fa fa-check"></i>Empty Elements</a></li>
</ul></li>
<li class="chapter" data-level="3.2" data-path="html-fundamentals.html"><a href="html-fundamentals.html#nesting-elements"><i class="fa fa-check"></i><b>3.2</b> Nesting Elements</a>
<ul>
<li class="chapter" data-level="" data-path="html-fundamentals.html"><a href="html-fundamentals.html#block-vs.-inline-elements"><i class="fa fa-check"></i>Block vs. Inline Elements</a></li>
</ul></li>
<li class="chapter" data-level="3.3" data-path="html-fundamentals.html"><a href="html-fundamentals.html#web-page-structure"><i class="fa fa-check"></i><b>3.3</b> Web Page Structure</a></li>
<li class="chapter" data-level="" data-path="html-fundamentals.html"><a href="html-fundamentals.html#resources-1"><i class="fa fa-check"></i>Resources</a></li>
</ul></li>
<li class="chapter" data-level="4" data-path="css-fundamentals.html"><a href="css-fundamentals.html"><i class="fa fa-check"></i><b>4</b> CSS Fundamentals</a>
<ul>
<li class="chapter" data-level="4.1" data-path="css-fundamentals.html"><a href="css-fundamentals.html#why-two-different-languages"><i class="fa fa-check"></i><b>4.1</b> Why Two Different Languages?</a></li>
<li class="chapter" data-level="4.2" data-path="css-fundamentals.html"><a href="css-fundamentals.html#including-css"><i class="fa fa-check"></i><b>4.2</b> Including CSS</a></li>
<li class="chapter" data-level="4.3" data-path="css-fundamentals.html"><a href="css-fundamentals.html#css-rules"><i class="fa fa-check"></i><b>4.3</b> CSS Rules</a>
<ul>
<li class="chapter" data-level="" data-path="css-fundamentals.html"><a href="css-fundamentals.html#css-selector-basics"><i class="fa fa-check"></i>CSS Selector Basics</a></li>
<li class="chapter" data-level="" data-path="css-fundamentals.html"><a href="css-fundamentals.html#css-property-basics"><i class="fa fa-check"></i>CSS Property Basics</a></li>
</ul></li>
<li class="chapter" data-level="4.4" data-path="css-fundamentals.html"><a href="css-fundamentals.html#the-cascade"><i class="fa fa-check"></i><b>4.4</b> The Cascade</a></li>
<li class="chapter" data-level="" data-path="css-fundamentals.html"><a href="css-fundamentals.html#resources-2"><i class="fa fa-check"></i>Resources</a></li>
</ul></li>
<li class="chapter" data-level="5" data-path="semantic-html.html"><a href="semantic-html.html"><i class="fa fa-check"></i><b>5</b> Semantic HTML</a>
<ul>
<li class="chapter" data-level="5.1" data-path="semantic-html.html"><a href="semantic-html.html#specific-html-elements"><i class="fa fa-check"></i><b>5.1</b> Specific HTML Elements</a>
<ul>
<li class="chapter" data-level="" data-path="semantic-html.html"><a href="semantic-html.html#hyperlinks"><i class="fa fa-check"></i>Hyperlinks</a></li>
<li class="chapter" data-level="" data-path="semantic-html.html"><a href="semantic-html.html#inline-textual-elements"><i class="fa fa-check"></i>Inline Textual Elements</a></li>
<li class="chapter" data-level="" data-path="semantic-html.html"><a href="semantic-html.html#images-and-media"><i class="fa fa-check"></i>Images and Media</a></li>
<li class="chapter" data-level="" data-path="semantic-html.html"><a href="semantic-html.html#headings"><i class="fa fa-check"></i>Headings</a></li>
<li class="chapter" data-level="" data-path="semantic-html.html"><a href="semantic-html.html#non-semantic-elements"><i class="fa fa-check"></i>Non-Semantic Elements</a></li>
<li class="chapter" data-level="" data-path="semantic-html.html"><a href="semantic-html.html#sectioning-elements"><i class="fa fa-check"></i>Sectioning Elements</a></li>
<li class="chapter" data-level="" data-path="semantic-html.html"><a href="semantic-html.html#tables"><i class="fa fa-check"></i>Tables</a></li>
<li class="chapter" data-level="" data-path="semantic-html.html"><a href="semantic-html.html#forms"><i class="fa fa-check"></i>Forms</a></li>
</ul></li>
<li class="chapter" data-level="5.2" data-path="semantic-html.html"><a href="semantic-html.html#aria-for-accessibility"><i class="fa fa-check"></i><b>5.2</b> ARIA for Accessibility</a>
<ul>
<li class="chapter" data-level="" data-path="semantic-html.html"><a href="semantic-html.html#aria-labeling"><i class="fa fa-check"></i>ARIA Labeling</a></li>
<li class="chapter" data-level="" data-path="semantic-html.html"><a href="semantic-html.html#aria-roles-and-landmarks"><i class="fa fa-check"></i>ARIA Roles and Landmarks</a></li>
<li class="chapter" data-level="" data-path="semantic-html.html"><a href="semantic-html.html#aria-and-interactivity"><i class="fa fa-check"></i>ARIA and Interactivity</a></li>
</ul></li>
<li class="chapter" data-level="" data-path="semantic-html.html"><a href="semantic-html.html#resources-3"><i class="fa fa-check"></i>Resources</a></li>
</ul></li>
<li class="chapter" data-level="6" data-path="css-selectors.html"><a href="css-selectors.html"><i class="fa fa-check"></i><b>6</b> CSS Selectors</a>
<ul>
<li class="chapter" data-level="6.1" data-path="css-selectors.html"><a href="css-selectors.html#basic-selectors"><i class="fa fa-check"></i><b>6.1</b> Basic Selectors</a>
<ul>
<li class="chapter" data-level="" data-path="css-selectors.html"><a href="css-selectors.html#type-selector"><i class="fa fa-check"></i>Type Selector</a></li>
<li class="chapter" data-level="" data-path="css-selectors.html"><a href="css-selectors.html#class-selector"><i class="fa fa-check"></i>Class Selector</a></li>
<li class="chapter" data-level="" data-path="css-selectors.html"><a href="css-selectors.html#id-selector"><i class="fa fa-check"></i>Id Selector</a></li>
</ul></li>
<li class="chapter" data-level="6.2" data-path="css-selectors.html"><a href="css-selectors.html#complex-selectors"><i class="fa fa-check"></i><b>6.2</b> Complex Selectors</a>
<ul>
<li class="chapter" data-level="" data-path="css-selectors.html"><a href="css-selectors.html#grouping-selector"><i class="fa fa-check"></i>Grouping Selector</a></li>
<li class="chapter" data-level="" data-path="css-selectors.html"><a href="css-selectors.html#compound-selector"><i class="fa fa-check"></i>Compound Selector</a></li>
<li class="chapter" data-level="" data-path="css-selectors.html"><a href="css-selectors.html#descendant-selector"><i class="fa fa-check"></i>Descendant Selector</a></li>
<li class="chapter" data-level="" data-path="css-selectors.html"><a href="css-selectors.html#pseudo-classes"><i class="fa fa-check"></i>Pseudo-classes</a></li>
<li class="chapter" data-level="" data-path="css-selectors.html"><a href="css-selectors.html#additional-selectors"><i class="fa fa-check"></i>Additional Selectors</a></li>
</ul></li>
<li class="chapter" data-level="6.3" data-path="css-selectors.html"><a href="css-selectors.html#selector-specificity"><i class="fa fa-check"></i><b>6.3</b> Selector Specificity</a></li>
<li class="chapter" data-level="" data-path="css-selectors.html"><a href="css-selectors.html#resources-4"><i class="fa fa-check"></i>Resources</a></li>
</ul></li>
<li class="chapter" data-level="7" data-path="css-properties.html"><a href="css-properties.html"><i class="fa fa-check"></i><b>7</b> CSS Properties</a>
<ul>
<li class="chapter" data-level="7.1" data-path="css-properties.html"><a href="css-properties.html#specifying-property-values"><i class="fa fa-check"></i><b>7.1</b> Specifying Property Values</a>
<ul>
<li class="chapter" data-level="" data-path="css-properties.html"><a href="css-properties.html#inherited-property-values"><i class="fa fa-check"></i>Inherited Property Values</a></li>
<li class="chapter" data-level="" data-path="css-properties.html"><a href="css-properties.html#css-units"><i class="fa fa-check"></i>Length Units & Sizes</a></li>
</ul></li>
<li class="chapter" data-level="7.2" data-path="css-properties.html"><a href="css-properties.html#fonts-and-text"><i class="fa fa-check"></i><b>7.2</b> Fonts and Text</a></li>
<li class="chapter" data-level="7.3" data-path="css-properties.html"><a href="css-properties.html#css-colors"><i class="fa fa-check"></i><b>7.3</b> Colors and Backgrounds</a>
<ul>
<li class="chapter" data-level="" data-path="css-properties.html"><a href="css-properties.html#backgrounds-and-images"><i class="fa fa-check"></i>Backgrounds and Images</a></li>
</ul></li>
<li class="chapter" data-level="7.4" data-path="css-properties.html"><a href="css-properties.html#box-model"><i class="fa fa-check"></i><b>7.4</b> Spacing with the Box Model</a>
<ul>
<li class="chapter" data-level="" data-path="css-properties.html"><a href="css-properties.html#padding"><i class="fa fa-check"></i>Padding</a></li>
<li class="chapter" data-level="" data-path="css-properties.html"><a href="css-properties.html#border"><i class="fa fa-check"></i>Border</a></li>
<li class="chapter" data-level="" data-path="css-properties.html"><a href="css-properties.html#margin"><i class="fa fa-check"></i>Margin</a></li>
<li class="chapter" data-level="" data-path="css-properties.html"><a href="css-properties.html#padding-vs.-margin"><i class="fa fa-check"></i>Padding vs. Margin</a></li>
<li class="chapter" data-level="" data-path="css-properties.html"><a href="css-properties.html#box-sizing"><i class="fa fa-check"></i>Box-Sizing</a></li>
</ul></li>
<li class="chapter" data-level="7.5" data-path="css-properties.html"><a href="css-properties.html#flow-layout"><i class="fa fa-check"></i><b>7.5</b> Flow Layout</a></li>
<li class="chapter" data-level="7.6" data-path="css-properties.html"><a href="css-properties.html#alternate-positioning"><i class="fa fa-check"></i><b>7.6</b> Alternate Positioning</a>
<ul>
<li class="chapter" data-level="" data-path="css-properties.html"><a href="css-properties.html#floating"><i class="fa fa-check"></i>Floating</a></li>
</ul></li>
<li class="chapter" data-level="7.7" data-path="css-properties.html"><a href="css-properties.html#flexbox"><i class="fa fa-check"></i><b>7.7</b> Flexbox</a></li>
<li class="chapter" data-level="" data-path="css-properties.html"><a href="css-properties.html#resources-5"><i class="fa fa-check"></i>Resources</a></li>
</ul></li>
<li class="chapter" data-level="8" data-path="responsive-css.html"><a href="responsive-css.html"><i class="fa fa-check"></i><b>8</b> Responsive CSS</a>
<ul>
<li class="chapter" data-level="8.1" data-path="responsive-css.html"><a href="responsive-css.html#mobile-first-design"><i class="fa fa-check"></i><b>8.1</b> Mobile-First Design</a>
<ul>
<li class="chapter" data-level="" data-path="responsive-css.html"><a href="responsive-css.html#mobile-first-design-principles"><i class="fa fa-check"></i>Mobile-First Design Principles</a></li>
<li class="chapter" data-level="" data-path="responsive-css.html"><a href="responsive-css.html#specifying-viewport"><i class="fa fa-check"></i>Specifying Viewport</a></li>
</ul></li>
<li class="chapter" data-level="8.2" data-path="responsive-css.html"><a href="responsive-css.html#media-queries"><i class="fa fa-check"></i><b>8.2</b> Media Queries</a>
<ul>
<li class="chapter" data-level="" data-path="responsive-css.html"><a href="responsive-css.html#example-responsive-flexbox"><i class="fa fa-check"></i>Example: Responsive Flexbox</a></li>
</ul></li>
<li class="chapter" data-level="" data-path="responsive-css.html"><a href="responsive-css.html#resources-6"><i class="fa fa-check"></i>Resources</a></li>
</ul></li>
<li class="chapter" data-level="9" data-path="css-frameworks.html"><a href="css-frameworks.html"><i class="fa fa-check"></i><b>9</b> CSS Frameworks</a>
<ul>
<li class="chapter" data-level="9.1" data-path="css-frameworks.html"><a href="css-frameworks.html#using-a-framework"><i class="fa fa-check"></i><b>9.1</b> Using a Framework</a>
<ul>
<li class="chapter" data-level="" data-path="css-frameworks.html"><a href="css-frameworks.html#including-a-framework"><i class="fa fa-check"></i>Including a Framework</a></li>
</ul></li>
<li class="chapter" data-level="9.2" data-path="css-frameworks.html"><a href="css-frameworks.html#bootstrap"><i class="fa fa-check"></i><b>9.2</b> Bootstrap</a>
<ul>
<li class="chapter" data-level="" data-path="css-frameworks.html"><a href="css-frameworks.html#utility-classes"><i class="fa fa-check"></i>Utility Classes</a></li>
<li class="chapter" data-level="" data-path="css-frameworks.html"><a href="css-frameworks.html#responsive-design"><i class="fa fa-check"></i>Responsive Design</a></li>
<li class="chapter" data-level="" data-path="css-frameworks.html"><a href="css-frameworks.html#the-grid"><i class="fa fa-check"></i>The Grid</a></li>
<li class="chapter" data-level="" data-path="css-frameworks.html"><a href="css-frameworks.html#components"><i class="fa fa-check"></i>Components</a></li>
</ul></li>
<li class="chapter" data-level="" data-path="css-frameworks.html"><a href="css-frameworks.html#resources-7"><i class="fa fa-check"></i>Resources</a></li>
</ul></li>
<li class="chapter" data-level="10" data-path="javascript.html"><a href="javascript.html"><i class="fa fa-check"></i><b>10</b> JavaScript Fundamentals</a>
<ul>
<li class="chapter" data-level="10.1" data-path="javascript.html"><a href="javascript.html#programming-with-javascript"><i class="fa fa-check"></i><b>10.1</b> Programming with JavaScript</a>
<ul>
<li class="chapter" data-level="" data-path="javascript.html"><a href="javascript.html#history-and-versions"><i class="fa fa-check"></i>History and Versions</a></li>
</ul></li>
<li class="chapter" data-level="10.2" data-path="javascript.html"><a href="javascript.html#running-javascript"><i class="fa fa-check"></i><b>10.2</b> Running JavaScript</a>
<ul>
<li class="chapter" data-level="" data-path="javascript.html"><a href="javascript.html#in-the-browser"><i class="fa fa-check"></i>In the Browser</a></li>
<li class="chapter" data-level="" data-path="javascript.html"><a href="javascript.html#on-the-command-line-with-node.js"><i class="fa fa-check"></i>On the Command-line with Node.js</a></li>
</ul></li>
<li class="chapter" data-level="10.3" data-path="javascript.html"><a href="javascript.html#writing-scripts"><i class="fa fa-check"></i><b>10.3</b> Writing Scripts</a>
<ul>
<li class="chapter" data-level="" data-path="javascript.html"><a href="javascript.html#strict-mode"><i class="fa fa-check"></i>Strict Mode</a></li>
</ul></li>
<li class="chapter" data-level="10.4" data-path="javascript.html"><a href="javascript.html#variables"><i class="fa fa-check"></i><b>10.4</b> Variables</a>
<ul>
<li class="chapter" data-level="" data-path="javascript.html"><a href="javascript.html#basic-data-types"><i class="fa fa-check"></i>Basic Data Types</a></li>
<li class="chapter" data-level="" data-path="javascript.html"><a href="javascript.html#arrays"><i class="fa fa-check"></i>Arrays</a></li>
<li class="chapter" data-level="" data-path="javascript.html"><a href="javascript.html#objects"><i class="fa fa-check"></i>Objects</a></li>
<li class="chapter" data-level="" data-path="javascript.html"><a href="javascript.html#type-coercion"><i class="fa fa-check"></i>Type Coercion</a></li>
</ul></li>
<li class="chapter" data-level="10.5" data-path="javascript.html"><a href="javascript.html#control-structures"><i class="fa fa-check"></i><b>10.5</b> Control Structures</a></li>
<li class="chapter" data-level="10.6" data-path="javascript.html"><a href="javascript.html#functions"><i class="fa fa-check"></i><b>10.6</b> Functions</a></li>
<li class="chapter" data-level="" data-path="javascript.html"><a href="javascript.html#resources-8"><i class="fa fa-check"></i>Resources</a></li>
</ul></li>
<li class="chapter" data-level="11" data-path="functional-programming.html"><a href="functional-programming.html"><i class="fa fa-check"></i><b>11</b> Functional Programming in JS</a>
<ul>
<li class="chapter" data-level="11.1" data-path="functional-programming.html"><a href="functional-programming.html#functions-are-variables"><i class="fa fa-check"></i><b>11.1</b> Functions ARE Variables</a>
<ul>
<li class="chapter" data-level="" data-path="functional-programming.html"><a href="functional-programming.html#anonymous-functions"><i class="fa fa-check"></i>Anonymous Functions</a></li>
</ul></li>
<li class="chapter" data-level="11.2" data-path="functional-programming.html"><a href="functional-programming.html#object-functions"><i class="fa fa-check"></i><b>11.2</b> Object Functions</a></li>
<li class="chapter" data-level="11.3" data-path="functional-programming.html"><a href="functional-programming.html#callback-functions"><i class="fa fa-check"></i><b>11.3</b> Callback Functions</a>
<ul>
<li class="chapter" data-level="" data-path="functional-programming.html"><a href="functional-programming.html#closures"><i class="fa fa-check"></i>Closures</a></li>
</ul></li>
<li class="chapter" data-level="11.4" data-path="functional-programming.html"><a href="functional-programming.html#functional-looping"><i class="fa fa-check"></i><b>11.4</b> Functional Looping</a>
<ul>
<li class="chapter" data-level="" data-path="functional-programming.html"><a href="functional-programming.html#map"><i class="fa fa-check"></i>Map</a></li>
<li class="chapter" data-level="" data-path="functional-programming.html"><a href="functional-programming.html#filter"><i class="fa fa-check"></i>Filter</a></li>
<li class="chapter" data-level="" data-path="functional-programming.html"><a href="functional-programming.html#reduce"><i class="fa fa-check"></i>Reduce</a></li>
</ul></li>
<li class="chapter" data-level="11.5" data-path="functional-programming.html"><a href="functional-programming.html#pure-functions"><i class="fa fa-check"></i><b>11.5</b> Pure Functions</a></li>
<li class="chapter" data-level="" data-path="functional-programming.html"><a href="functional-programming.html#resources-9"><i class="fa fa-check"></i>Resources</a></li>
</ul></li>
<li class="chapter" data-level="12" data-path="dom.html"><a href="dom.html"><i class="fa fa-check"></i><b>12</b> Document Object Model (DOM)</a>
<ul>
<li class="chapter" data-level="12.1" data-path="dom.html"><a href="dom.html#the-dom-api"><i class="fa fa-check"></i><b>12.1</b> The DOM API</a>
<ul>
<li class="chapter" data-level="" data-path="dom.html"><a href="dom.html#global-variables"><i class="fa fa-check"></i>Global Variables</a></li>
</ul></li>
<li class="chapter" data-level="12.2" data-path="dom.html"><a href="dom.html#dom-manipulation"><i class="fa fa-check"></i><b>12.2</b> DOM Manipulation</a>
<ul>
<li class="chapter" data-level="" data-path="dom.html"><a href="dom.html#referencing-html-elements"><i class="fa fa-check"></i>Referencing HTML Elements</a></li>
<li class="chapter" data-level="" data-path="dom.html"><a href="dom.html#modifying-html-elements"><i class="fa fa-check"></i>Modifying HTML Elements</a></li>
<li class="chapter" data-level="" data-path="dom.html"><a href="dom.html#modifying-the-dom-tree"><i class="fa fa-check"></i>Modifying the DOM Tree</a></li>
<li class="chapter" data-level="" data-path="dom.html"><a href="dom.html#accessibility"><i class="fa fa-check"></i>Accessibility</a></li>
</ul></li>
<li class="chapter" data-level="12.3" data-path="dom.html"><a href="dom.html#listening-for-events"><i class="fa fa-check"></i><b>12.3</b> Listening for Events</a>
<ul>
<li class="chapter" data-level="" data-path="dom.html"><a href="dom.html#types-of-events"><i class="fa fa-check"></i>Types of Events</a></li>
<li class="chapter" data-level="" data-path="dom.html"><a href="dom.html#event-driven-programming"><i class="fa fa-check"></i>Event-Driven Programming</a></li>
</ul></li>
<li class="chapter" data-level="" data-path="dom.html"><a href="dom.html#resources-10"><i class="fa fa-check"></i>Resources</a></li>
</ul></li>
<li class="chapter" data-level="13" data-path="javascript-libraries.html"><a href="javascript-libraries.html"><i class="fa fa-check"></i><b>13</b> JavaScript Libraries</a>
<ul>
<li class="chapter" data-level="13.1" data-path="javascript-libraries.html"><a href="javascript-libraries.html#including-a-library"><i class="fa fa-check"></i><b>13.1</b> Including a Library</a></li>
<li class="chapter" data-level="13.2" data-path="javascript-libraries.html"><a href="javascript-libraries.html#example-jquery"><i class="fa fa-check"></i><b>13.2</b> Example: jQuery</a>
<ul>
<li class="chapter" data-level="" data-path="javascript-libraries.html"><a href="javascript-libraries.html#maniputing-the-dom"><i class="fa fa-check"></i>Maniputing the DOM</a></li>
<li class="chapter" data-level="" data-path="javascript-libraries.html"><a href="javascript-libraries.html#handling-events"><i class="fa fa-check"></i>Handling Events</a></li>
<li class="chapter" data-level="" data-path="javascript-libraries.html"><a href="javascript-libraries.html#and-more"><i class="fa fa-check"></i>And more!</a></li>
</ul></li>
<li class="chapter" data-level="" data-path="javascript-libraries.html"><a href="javascript-libraries.html#resources-11"><i class="fa fa-check"></i>Resources</a></li>
</ul></li>
<li class="chapter" data-level="14" data-path="es6.html"><a href="es6.html"><i class="fa fa-check"></i><b>14</b> ES6+ Syntax</a>
<ul>
<li class="chapter" data-level="14.1" data-path="es6.html"><a href="es6.html#es6-syntax-features"><i class="fa fa-check"></i><b>14.1</b> ES6+ Syntax Features</a>
<ul>
<li class="chapter" data-level="" data-path="es6.html"><a href="es6.html#arrow-functions"><i class="fa fa-check"></i>Arrow Functions</a></li>
<li class="chapter" data-level="" data-path="es6.html"><a href="es6.html#destructuring"><i class="fa fa-check"></i>Destructuring</a></li>
<li class="chapter" data-level="" data-path="es6.html"><a href="es6.html#spreading"><i class="fa fa-check"></i>Spreading</a></li>
<li class="chapter" data-level="" data-path="es6.html"><a href="es6.html#template-strings"><i class="fa fa-check"></i>Template Strings</a></li>
</ul></li>
<li class="chapter" data-level="14.2" data-path="es6.html"><a href="es6.html#modules"><i class="fa fa-check"></i><b>14.2</b> Modules</a>
<ul>
<li class="chapter" data-level="" data-path="es6.html"><a href="es6.html#module-syntax"><i class="fa fa-check"></i>Module Syntax</a></li>
</ul></li>
<li class="chapter" data-level="14.3" data-path="es6.html"><a href="es6.html#es6-classes"><i class="fa fa-check"></i><b>14.3</b> Classes</a>
<ul>
<li class="chapter" data-level="" data-path="es6.html"><a href="es6.html#why-classes"><i class="fa fa-check"></i>Why Classes?</a></li>
<li class="chapter" data-level="" data-path="es6.html"><a href="es6.html#review-classes-in-java"><i class="fa fa-check"></i>Review: Classes in Java</a></li>
<li class="chapter" data-level="" data-path="es6.html"><a href="es6.html#es6-class-syntax"><i class="fa fa-check"></i>ES6 Class Syntax</a></li>
<li class="chapter" data-level="" data-path="es6.html"><a href="es6.html#inheritance"><i class="fa fa-check"></i>Inheritance</a></li>
<li><a href="es6.html#working-with-this">Working with <code>this</code></a></li>
</ul></li>
</ul></li>
<li class="chapter" data-level="15" data-path="react.html"><a href="react.html"><i class="fa fa-check"></i><b>15</b> Introduction to React</a>
<ul>
<li class="chapter" data-level="15.1" data-path="react.html"><a href="react.html#react-vite-setup"><i class="fa fa-check"></i><b>15.1</b> Getting Set Up: React and Vite</a>
<ul>
<li class="chapter" data-level="" data-path="react.html"><a href="react.html#running-the-development-server"><i class="fa fa-check"></i>Running the Development Server</a></li>
<li class="chapter" data-level="" data-path="react.html"><a href="react.html#project-structure"><i class="fa fa-check"></i>Project Structure</a></li>
</ul></li>
<li class="chapter" data-level="15.2" data-path="react.html"><a href="react.html#jsx"><i class="fa fa-check"></i><b>15.2</b> JSX</a>
<ul>
<li class="chapter" data-level="" data-path="react.html"><a href="react.html#inline-expressions"><i class="fa fa-check"></i>Inline Expressions</a></li>
</ul></li>
<li class="chapter" data-level="15.3" data-path="react.html"><a href="react.html#react-components"><i class="fa fa-check"></i><b>15.3</b> React Components</a>
<ul>
<li class="chapter" data-level="" data-path="react.html"><a href="react.html#component-organization"><i class="fa fa-check"></i>Component Organization</a></li>
<li class="chapter" data-level="" data-path="react.html"><a href="react.html#deprecated-alternative-class-components"><i class="fa fa-check"></i>Deprecated Alternative: Class Components</a></li>
</ul></li>
<li class="chapter" data-level="15.4" data-path="react.html"><a href="react.html#props"><i class="fa fa-check"></i><b>15.4</b> Properties (<code>props</code>)</a>
<ul>
<li class="chapter" data-level="" data-path="react.html"><a href="react.html#props-and-composition"><i class="fa fa-check"></i>Props and Composition</a></li>
</ul></li>
<li class="chapter" data-level="" data-path="react.html"><a href="react.html#resources-12"><i class="fa fa-check"></i>Resources</a></li>
</ul></li>
<li class="chapter" data-level="16" data-path="interactive-react.html"><a href="interactive-react.html"><i class="fa fa-check"></i><b>16</b> Interactive React</a>
<ul>
<li class="chapter" data-level="16.1" data-path="interactive-react.html"><a href="interactive-react.html#handling-events-in-react"><i class="fa fa-check"></i><b>16.1</b> Handling Events in React</a></li>
<li class="chapter" data-level="16.2" data-path="interactive-react.html"><a href="interactive-react.html#state-and-hooks"><i class="fa fa-check"></i><b>16.2</b> State and Hooks</a>
<ul>
<li class="chapter" data-level="" data-path="interactive-react.html"><a href="interactive-react.html#updating-state"><i class="fa fa-check"></i>Updating State</a></li>
<li class="chapter" data-level="" data-path="interactive-react.html"><a href="interactive-react.html#state-vs.-props"><i class="fa fa-check"></i>State vs. Props</a></li>
<li class="chapter" data-level="" data-path="interactive-react.html"><a href="interactive-react.html#lifting-up-state"><i class="fa fa-check"></i>Lifting Up State</a></li>
</ul></li>
<li class="chapter" data-level="16.3" data-path="interactive-react.html"><a href="interactive-react.html#specific-interactions"><i class="fa fa-check"></i><b>16.3</b> Specific Interactions</a>
<ul>
<li class="chapter" data-level="" data-path="interactive-react.html"><a href="interactive-react.html#working-with-forms"><i class="fa fa-check"></i>Working with Forms</a></li>
<li class="chapter" data-level="" data-path="interactive-react.html"><a href="interactive-react.html#fetching-data-via-ajax"><i class="fa fa-check"></i>Fetching Data via AJAX</a></li>
</ul></li>
<li class="chapter" data-level="" data-path="interactive-react.html"><a href="interactive-react.html#resources-13"><i class="fa fa-check"></i>Resources</a></li>
</ul></li>
<li class="chapter" data-level="17" data-path="client-side-routing.html"><a href="client-side-routing.html"><i class="fa fa-check"></i><b>17</b> Client-Side Routing</a>
<ul>
<li class="chapter" data-level="17.1" data-path="client-side-routing.html"><a href="client-side-routing.html#single-page-applications"><i class="fa fa-check"></i><b>17.1</b> Single-Page Applications</a></li>
<li class="chapter" data-level="17.2" data-path="client-side-routing.html"><a href="client-side-routing.html#react-router"><i class="fa fa-check"></i><b>17.2</b> React-Router</a>
<ul>
<li class="chapter" data-level="" data-path="client-side-routing.html"><a href="client-side-routing.html#routing"><i class="fa fa-check"></i>Routing</a></li>
<li class="chapter" data-level="" data-path="client-side-routing.html"><a href="client-side-routing.html#linking"><i class="fa fa-check"></i>Linking</a></li>
<li class="chapter" data-level="" data-path="client-side-routing.html"><a href="client-side-routing.html#react-router-and-hosting"><i class="fa fa-check"></i>React Router and Hosting</a></li>
</ul></li>
<li class="chapter" data-level="" data-path="client-side-routing.html"><a href="client-side-routing.html#resources-14"><i class="fa fa-check"></i>Resources</a></li>
</ul></li>
<li class="chapter" data-level="18" data-path="ajax.html"><a href="ajax.html"><i class="fa fa-check"></i><b>18</b> AJAX Requests</a>
<ul>
<li class="chapter" data-level="18.1" data-path="ajax.html"><a href="ajax.html#ajax-1"><i class="fa fa-check"></i><b>18.1</b> AJAX</a>
<ul>
<li class="chapter" data-level="" data-path="ajax.html"><a href="ajax.html#xml-and-json"><i class="fa fa-check"></i>XML and JSON</a></li>
</ul></li>
<li class="chapter" data-level="18.2" data-path="ajax.html"><a href="ajax.html#fetching-data"><i class="fa fa-check"></i><b>18.2</b> Fetching Data</a></li>
<li class="chapter" data-level="18.3" data-path="ajax.html"><a href="ajax.html#asynchronous-programming"><i class="fa fa-check"></i><b>18.3</b> Asynchronous Programming</a>
<ul>
<li class="chapter" data-level="" data-path="ajax.html"><a href="ajax.html#chaining-promises"><i class="fa fa-check"></i>Chaining Promises</a></li>
<li class="chapter" data-level="" data-path="ajax.html"><a href="ajax.html#handling-errors"><i class="fa fa-check"></i>Handling Errors</a></li>
<li class="chapter" data-level="" data-path="ajax.html"><a href="ajax.html#other-data-formats"><i class="fa fa-check"></i>Other Data Formats</a></li>
</ul></li>
<li class="chapter" data-level="" data-path="ajax.html"><a href="ajax.html#resources-15"><i class="fa fa-check"></i>Resources</a></li>
</ul></li>
<li class="chapter" data-level="19" data-path="firebase.html"><a href="firebase.html"><i class="fa fa-check"></i><b>19</b> Firebase</a>
<ul>
<li class="chapter" data-level="19.1" data-path="firebase.html"><a href="firebase.html#setting-up-firebase"><i class="fa fa-check"></i><b>19.1</b> Setting up Firebase</a>
<ul>
<li class="chapter" data-level="" data-path="firebase.html"><a href="firebase.html#creating-a-project"><i class="fa fa-check"></i>Creating a Project</a></li>
<li class="chapter" data-level="" data-path="firebase.html"><a href="firebase.html#including-firebase-in-react"><i class="fa fa-check"></i>Including Firebase in React</a></li>
<li class="chapter" data-level="" data-path="firebase.html"><a href="firebase.html#adding-collaborators-to-a-project"><i class="fa fa-check"></i>Adding Collaborators to a Project</a></li>
</ul></li>
<li class="chapter" data-level="19.2" data-path="firebase.html"><a href="firebase.html#realtime-database"><i class="fa fa-check"></i><b>19.2</b> Realtime Database</a>
<ul>
<li class="chapter" data-level="" data-path="firebase.html"><a href="firebase.html#setting-up-the-database"><i class="fa fa-check"></i>Setting Up the Database</a></li>
<li class="chapter" data-level="" data-path="firebase.html"><a href="firebase.html#data-references"><i class="fa fa-check"></i>Data References</a></li>
<li class="chapter" data-level="" data-path="firebase.html"><a href="firebase.html#writing-data"><i class="fa fa-check"></i>Writing Data</a></li>
<li class="chapter" data-level="" data-path="firebase.html"><a href="firebase.html#listening-for-data-changes"><i class="fa fa-check"></i>Listening for Data Changes</a></li>
<li class="chapter" data-level="" data-path="firebase.html"><a href="firebase.html#firebase-arrays"><i class="fa fa-check"></i>Firebase Arrays</a></li>
</ul></li>
<li class="chapter" data-level="19.3" data-path="firebase.html"><a href="firebase.html#user-authentication"><i class="fa fa-check"></i><b>19.3</b> User Authentication</a>
<ul>
<li class="chapter" data-level="" data-path="firebase.html"><a href="firebase.html#signing-in-with-firebaseui"><i class="fa fa-check"></i>Signing In with FirebaseUI</a></li>
<li class="chapter" data-level="" data-path="firebase.html"><a href="firebase.html#managing-the-user"><i class="fa fa-check"></i>Managing the User</a></li>
</ul></li>
<li class="chapter" data-level="19.4" data-path="firebase.html"><a href="firebase.html#firebase-storage"><i class="fa fa-check"></i><b>19.4</b> Firebase Storage</a>
<ul>
<li class="chapter" data-level="" data-path="firebase.html"><a href="firebase.html#file-inputs"><i class="fa fa-check"></i>File Inputs</a></li>
<li class="chapter" data-level="" data-path="firebase.html"><a href="firebase.html#uploading-files"><i class="fa fa-check"></i>Uploading Files</a></li>
</ul></li>
<li class="chapter" data-level="" data-path="firebase.html"><a href="firebase.html#resources-16"><i class="fa fa-check"></i>Resources</a></li>
</ul></li>
<li class="appendix"><span><b>Appendices & Special Topics</b></span></li>
<li class="chapter" data-level="A" data-path="code-style-guide.html"><a href="code-style-guide.html"><i class="fa fa-check"></i><b>A</b> Code Style Guide</a>
<ul>
<li class="chapter" data-level="A.1" data-path="code-style-guide.html"><a href="code-style-guide.html#html-guidelines"><i class="fa fa-check"></i><b>A.1</b> HTML Guidelines</a>
<ul>
<li class="chapter" data-level="" data-path="code-style-guide.html"><a href="code-style-guide.html#spacing"><i class="fa fa-check"></i>Spacing</a></li>
<li class="chapter" data-level="" data-path="code-style-guide.html"><a href="code-style-guide.html#specific-elements"><i class="fa fa-check"></i>Specific Elements</a></li>
<li class="chapter" data-level="" data-path="code-style-guide.html"><a href="code-style-guide.html#comments-in-html"><i class="fa fa-check"></i>Comments in HTML</a></li>
</ul></li>
<li class="chapter" data-level="A.2" data-path="code-style-guide.html"><a href="code-style-guide.html#css-guidelines"><i class="fa fa-check"></i><b>A.2</b> CSS Guidelines</a>
<ul>
<li class="chapter" data-level="A.2.1" data-path="code-style-guide.html"><a href="code-style-guide.html#spacing-1"><i class="fa fa-check"></i><b>A.2.1</b> Spacing</a></li>
<li class="chapter" data-level="A.2.2" data-path="code-style-guide.html"><a href="code-style-guide.html#selectors"><i class="fa fa-check"></i><b>A.2.2</b> Selectors</a></li>
<li class="chapter" data-level="A.2.3" data-path="code-style-guide.html"><a href="code-style-guide.html#class-names"><i class="fa fa-check"></i><b>A.2.3</b> Class Names</a></li>
<li class="chapter" data-level="A.2.4" data-path="code-style-guide.html"><a href="code-style-guide.html#specific-properties"><i class="fa fa-check"></i><b>A.2.4</b> Specific Properties</a></li>
<li class="chapter" data-level="A.2.5" data-path="code-style-guide.html"><a href="code-style-guide.html#responsive-css-1"><i class="fa fa-check"></i><b>A.2.5</b> Responsive CSS</a></li>
<li class="chapter" data-level="A.2.6" data-path="code-style-guide.html"><a href="code-style-guide.html#comments-in-css"><i class="fa fa-check"></i><b>A.2.6</b> Comments in CSS</a></li>
</ul></li>
<li class="chapter" data-level="A.3" data-path="code-style-guide.html"><a href="code-style-guide.html#javascript-guidelines"><i class="fa fa-check"></i><b>A.3</b> JavaScript Guidelines</a>
<ul>
<li class="chapter" data-level="A.3.1" data-path="code-style-guide.html"><a href="code-style-guide.html#variables-1"><i class="fa fa-check"></i><b>A.3.1</b> Variables</a></li>
<li class="chapter" data-level="A.3.2" data-path="code-style-guide.html"><a href="code-style-guide.html#functions-1"><i class="fa fa-check"></i><b>A.3.2</b> Functions</a></li>
<li class="chapter" data-level="A.3.3" data-path="code-style-guide.html"><a href="code-style-guide.html#comments-in-javascript"><i class="fa fa-check"></i><b>A.3.3</b> Comments in JavaScript</a></li>
<li class="chapter" data-level="A.3.4" data-path="code-style-guide.html"><a href="code-style-guide.html#miscellaneous-javascript-guidelines"><i class="fa fa-check"></i><b>A.3.4</b> Miscellaneous JavaScript Guidelines</a></li>
</ul></li>
<li class="chapter" data-level="A.4" data-path="code-style-guide.html"><a href="code-style-guide.html#react-guidelines"><i class="fa fa-check"></i><b>A.4</b> React Guidelines</a>
<ul>
<li class="chapter" data-level="A.4.1" data-path="code-style-guide.html"><a href="code-style-guide.html#components-1"><i class="fa fa-check"></i><b>A.4.1</b> Components</a></li>
<li class="chapter" data-level="A.4.2" data-path="code-style-guide.html"><a href="code-style-guide.html#mapping-data"><i class="fa fa-check"></i><b>A.4.2</b> Mapping Data</a></li>
<li class="chapter" data-level="A.4.3" data-path="code-style-guide.html"><a href="code-style-guide.html#state"><i class="fa fa-check"></i><b>A.4.3</b> State</a></li>
<li class="chapter" data-level="A.4.4" data-path="code-style-guide.html"><a href="code-style-guide.html#events-and-forms"><i class="fa fa-check"></i><b>A.4.4</b> Events and Forms</a></li>
</ul></li>
<li class="chapter" data-level="A.5" data-path="code-style-guide.html"><a href="code-style-guide.html#miscellaneous-guidelines"><i class="fa fa-check"></i><b>A.5</b> Miscellaneous Guidelines</a></li>
</ul></li>
<li class="chapter" data-level="B" data-path="jest.html"><a href="jest.html"><i class="fa fa-check"></i><b>B</b> Testing with Jest</a>
<ul>
<li class="chapter" data-level="B.1" data-path="jest.html"><a href="jest.html#testing"><i class="fa fa-check"></i><b>B.1</b> Testing</a></li>
<li class="chapter" data-level="B.2" data-path="jest.html"><a href="jest.html#testing-with-jest"><i class="fa fa-check"></i><b>B.2</b> Testing with Jest</a></li>
<li class="chapter" data-level="B.3" data-path="jest.html"><a href="jest.html#writing-a-test"><i class="fa fa-check"></i><b>B.3</b> Writing a Test</a>
<ul>
<li class="chapter" data-level="" data-path="jest.html"><a href="jest.html#assertions-and-matchers"><i class="fa fa-check"></i>Assertions and Matchers</a></li>
<li class="chapter" data-level="" data-path="jest.html"><a href="jest.html#organizing-tests"><i class="fa fa-check"></i>Organizing Tests</a></li>
<li class="chapter" data-level="" data-path="jest.html"><a href="jest.html#running-the-tests"><i class="fa fa-check"></i>Running the Tests</a></li>
<li class="chapter" data-level="" data-path="jest.html"><a href="jest.html#practice"><i class="fa fa-check"></i>Practice</a></li>
</ul></li>
<li class="chapter" data-level="B.4" data-path="jest.html"><a href="jest.html#testing-web-apps-with-jest"><i class="fa fa-check"></i><b>B.4</b> Testing Web Apps with Jest</a>
<ul>
<li class="chapter" data-level="" data-path="jest.html"><a href="jest.html#practice-1"><i class="fa fa-check"></i>Practice</a></li>
</ul></li>
</ul></li>
<li class="chapter" data-level="C" data-path="webpack.html"><a href="webpack.html"><i class="fa fa-check"></i><b>C</b> Lab: Webpack</a>
<ul>
<li class="chapter" data-level="C.1" data-path="webpack.html"><a href="webpack.html#what-is-webpack"><i class="fa fa-check"></i><b>C.1</b> What is Webpack?</a></li>
<li class="chapter" data-level="C.2" data-path="webpack.html"><a href="webpack.html#getting-started"><i class="fa fa-check"></i><b>C.2</b> Getting Started</a></li>
<li class="chapter" data-level="C.3" data-path="webpack.html"><a href="webpack.html#webpack.config.js"><i class="fa fa-check"></i><b>C.3</b> <code>webpack.config.js</code></a>
<ul>
<li><a href="webpack.html#entry-and-output"><code>entry</code> and <code>output</code></a></li>
</ul></li>
<li class="chapter" data-level="C.4" data-path="webpack.html"><a href="webpack.html#loaders"><i class="fa fa-check"></i><b>C.4</b> Loaders</a>
<ul>
<li class="chapter" data-level="" data-path="webpack.html"><a href="webpack.html#babel-loader"><i class="fa fa-check"></i>Babel Loader</a></li>
<li class="chapter" data-level="" data-path="webpack.html"><a href="webpack.html#clean-up-bath"><i class="fa fa-check"></i>Clean up :bath:</a></li>
<li class="chapter" data-level="" data-path="webpack.html"><a href="webpack.html#further-loader-practice"><i class="fa fa-check"></i>Further Loader Practice</a></li>
</ul></li>
</ul></li>
<li class="chapter" data-level="D" data-path="class-components.html"><a href="class-components.html"><i class="fa fa-check"></i><b>D</b> React Class Components</a>
<ul>
<li class="chapter" data-level="D.1" data-path="class-components.html"><a href="class-components.html#props-in-class-components"><i class="fa fa-check"></i><b>D.1</b> Props in Class Components</a></li>
<li class="chapter" data-level="D.2" data-path="class-components.html"><a href="class-components.html#handling-events-in-class-components"><i class="fa fa-check"></i><b>D.2</b> Handling Events in Class Components</a>
<ul>
<li><a href="class-components.html#accessing-this-component-from-events">Accessing <code>this</code> Component from Events</a></li>
</ul></li>
<li class="chapter" data-level="D.3" data-path="class-components.html"><a href="class-components.html#state-in-class-components"><i class="fa fa-check"></i><b>D.3</b> State in Class Components</a>
<ul>
<li class="chapter" data-level="" data-path="class-components.html"><a href="class-components.html#changing-the-state"><i class="fa fa-check"></i>Changing the State</a></li>
</ul></li>
<li class="chapter" data-level="D.4" data-path="class-components.html"><a href="class-components.html#the-component-lifecycle"><i class="fa fa-check"></i><b>D.4</b> The Component Lifecycle</a>
<ul>
<li class="chapter" data-level="" data-path="class-components.html"><a href="class-components.html#lifecycle-example-fetching-data-via-ajax"><i class="fa fa-check"></i>Lifecycle Example: Fetching Data via AJAX</a></li>
</ul></li>
<li class="chapter" data-level="" data-path="class-components.html"><a href="class-components.html#resources-17"><i class="fa fa-check"></i>Resources</a></li>
</ul></li>
<li class="chapter" data-level="E" data-path="css-in-js.html"><a href="css-in-js.html"><i class="fa fa-check"></i><b>E</b> CSS in JS</a>
<ul>
<li class="chapter" data-level="E.1" data-path="css-in-js.html"><a href="css-in-js.html#why-css-in-js"><i class="fa fa-check"></i><b>E.1</b> Why CSS in JS?</a></li>
<li class="chapter" data-level="E.2" data-path="css-in-js.html"><a href="css-in-js.html#react-inline-styles"><i class="fa fa-check"></i><b>E.2</b> React Inline Styles</a></li>
<li class="chapter" data-level="E.3" data-path="css-in-js.html"><a href="css-in-js.html#aphrodite"><i class="fa fa-check"></i><b>E.3</b> Aphrodite</a></li>
<li class="chapter" data-level="E.4" data-path="css-in-js.html"><a href="css-in-js.html#css-modules"><i class="fa fa-check"></i><b>E.4</b> CSS Modules</a>
<ul>
<li class="chapter" data-level="" data-path="css-in-js.html"><a href="css-in-js.html#ejecting-from-create-react-app"><i class="fa fa-check"></i>Ejecting from Create React App</a></li>
<li class="chapter" data-level="" data-path="css-in-js.html"><a href="css-in-js.html#composing-classes"><i class="fa fa-check"></i>Composing Classes</a></li>
</ul></li>
<li class="chapter" data-level="" data-path="css-in-js.html"><a href="css-in-js.html#resources-18"><i class="fa fa-check"></i>Resources</a></li>
</ul></li>
<li class="chapter" data-level="F" data-path="redux.html"><a href="redux.html"><i class="fa fa-check"></i><b>F</b> Redux</a></li>
<li class="chapter" data-level="G" data-path="react-native.html"><a href="react-native.html"><i class="fa fa-check"></i><b>G</b> React Native</a>
<ul>
<li class="chapter" data-level="G.1" data-path="react-native.html"><a href="react-native.html#getting-setup"><i class="fa fa-check"></i><b>G.1</b> Getting Setup</a>
<ul>
<li class="chapter" data-level="" data-path="react-native.html"><a href="react-native.html#running-react-native-apps"><i class="fa fa-check"></i>Running React Native Apps</a></li>
</ul></li>
<li class="chapter" data-level="G.2" data-path="react-native.html"><a href="react-native.html#react-native-apps"><i class="fa fa-check"></i><b>G.2</b> React Native Apps</a>
<ul>
<li class="chapter" data-level="" data-path="react-native.html"><a href="react-native.html#styling-react-native"><i class="fa fa-check"></i>Styling React Native</a></li>
<li class="chapter" data-level="" data-path="react-native.html"><a href="react-native.html#interaction"><i class="fa fa-check"></i>Interaction</a></li>
<li class="chapter" data-level="" data-path="react-native.html"><a href="react-native.html#lists-and-data"><i class="fa fa-check"></i>Lists and Data</a></li>
</ul></li>
</ul></li>
<li class="divider"></li>
<li><a href="https://github.com/rstudio/bookdown" target="blank">Published with bookdown</a></li>
</ul>
</nav>
</div>
<div class="book-body">
<div class="body-inner">
<div class="book-header" role="navigation">
<h1>
<i class="fa fa-circle-o-notch fa-spin"></i><a href="./">Client-Side Web Development</a>
</h1>
</div>
<div class="page-wrapper" tabindex="-1" role="main">
<div class="page-inner">
<section class="normal" id="section-">
<div id="firebase" class="section level1" number="19">
<h1><span class="header-section-number">Chapter 19</span> Firebase</h1>
<p>This chapter discusses how to integrate and use the <a href="https://firebase.google.com/"><strong>Firebase</strong></a> web service in a client-side application (using React). Firebase is a web service that provides tools and infrastructure for use in creating web and mobile apps that store data online in the cloud (a “web backend solution”). In effect, Firebase acts as a <em>server</em> that can host information for you, so that you can just build client-side applications without needing to program a web server.</p>
<ul>
<li>Firebase is owned and maintained by Google, but will still work perfectly fine with Facebook’s React framework.</li>
</ul>
<p>In particular, this chapter will discuss the following features of Firebase:</p>
<ol style="list-style-type: decimal">
<li><p>The Firebase service also provide a number of “database” systems. This chapter describes how to use the <a href="https://firebase.google.com/docs/database/"><strong>realtime database</strong></a>, which provides a simple <a href="https://en.wikipedia.org/wiki/NoSQL">NoSql</a>-style database: you can think of it as a <em>single giant JSON object in the Cloud</em>. Firebase provides methods that can be used to refer to this object and its properties, make changes to the object. Most importantly, it provides the ability to “listen” for changes made by others so that the page can automatically update based on actions taken by other users. In effect you can create a <strong>data binding</strong> between clients and the server, so that if you update data on one machine, that change automatically appears on another.</p>
<p>Firebase also offers additional database structures. <a href="https://firebase.google.com/docs/firestore">Firestore</a> is another NoSQL (document-based) database, but focused more on one-time data fetch queries rather than the continuous data binding provided by the realtime database. This chapter focuses on the Realtime Database as an easier-to-learn system and to practice data binding. <a href="https://firebase.google.com/docs/storage">Firebase Storage</a> is used for storing larger data elements (anything that can’t be defined in JSON), such as images or videos, and is described at the end of the chapter.</p></li>
<li><p>The Firebase service also offers a client-side based system for performing <a href="https://firebase.google.com/docs/auth/"><strong>user authentication</strong></a>, or allowing users to “sign in” to your application and have particular information associated with them. It’s possible to have users sign up with an email and password, or even using an external service (e.g., “sign in with Google”). Firebase also provides a way to manage all those extra interactions associated with accounts, like being able to reset passwords or confirm email addresses. And this is all performed securely from the client-side, without the need to set up an additional server to perform OAuth work.</p></li>
</ol>
<p>These features mean that Firebase can be a go-to back-end for producing a client-side app that involves persisted data (like user accounts). And its <a href="https://firebase.google.com/pricing/">free service tier</a> is well-suited for any development app.</p>
<p class="alert alert-warning">
This chapter details how to use <strong>version 9+</strong> of the Firebase library, released in <em>August 2021</em>—and in particular its <a href="https://firebase.google.com/docs/web/modular-upgrade"><em>modular API</em></a> (which allows for smaller and more efficient bundles when using webpack and React). Note that while this version is conceptually the same as previous versions, the module syntax for calling and importing functions is different. See the upgrade guide for details. Be careful when looking up examples and resources that they’re use the same version as you!
</p>
<p>Note that Firebase also provides <a href="https://firebase.google.com/docs/hosting"><strong>Firebase Hosting</strong></a> for hosting and serving web applications. This is particularly useful for hosting single-page-applications, such as those <a href="client-side-routing.html#react-router-and-hosting">built with React Router</a>. Hosting does not require any modifications to your source code, so is not discussed here.</p>
<div id="setting-up-firebase" class="section level2" number="19.1">
<h2><span class="header-section-number">19.1</span> Setting up Firebase</h2>
<p>Because Firebase is a cloud service, you will need to set it up externally in order to use it in your web application. Firebase setup and configuration is handled on Firebase’s website at <a href="https://firebase.google.com/" class="uri">https://firebase.google.com/</a>, and in particular in the <a href="https://console.firebase.google.com"><strong>Firebase Web Console</strong></a> where you can manage individual projects.</p>
<p class="alert alert-success">
When developing a Firebase app, keep the Web Console open all the time so you can check on database, user list, etc!
</p>
<div id="creating-a-project" class="section level3 unnumbered">
<h3>Creating a Project</h3>
<p>In order to use Firebase in your web app, you will need to <em>sign up for the service</em>. Visit <strong><a href="https://firebase.google.com/" class="uri">https://firebase.google.com/</a></strong> and click the “Get Started” button to do so. You will need to sign in with a Google account (e.g., a UW account if you’ve set up Google integration). Signing up will direct you to the Firebase Web Console.</p>
<p>In the Web Console, you can manage all of your “projects”—one per application you’ve created (think: per repository). Each project will track its own database of information, its own set of users, etc.</p>
<p>You can create a project by clicking the <em>“Add Project”</em> button. On the next screen, you’ll need to give the app a <em>unique</em> name. Naming the project after your app is a good idea. This name is used internally by the Firebase syste; it won’t necessarily be visible to your users, though if you use <a href="https://firebase.google.com/docs/hosting"><strong>Firebase Hosting</strong></a> then the project name will be part of the default URL for the application.</p>
<ul>
<li><em>Recommendation</em>: <strong>do not</strong> enable Google Analytics for your projects!</li>
</ul>
<p>Once you’ve created the project, you will be taken to the <strong>Web Console</strong> for that project. This is a web page where you will be able to manage the configuration of the project, the users who have signed up, and any data in the database. In particular, note the navigation menu on the left-hand side: you will use this to access different parts of your project (<em>Realtime Database</em> to manage the database, and <em>Authentication</em> to manage users)—expand the <em>“Build”</em> dropdown to navigate.</p>
<div class="figure">
<img src="img/firebase/firebase-nav3.png" alt="" />
<p class="caption">Firebase navigation menu</p>
</div>
</div>
<div id="including-firebase-in-react" class="section level3 unnumbered">
<h3>Including Firebase in React</h3>
<p>In order to use Firebase in a web app (including a React app), you will need to add the Firebase library to your web page, as well as some specify some configuration data to connect to the correct Firebase project.</p>
<p>From the project’s Web Console page, click the button (it look like a <code></></code> in the above image) to add Firebase to a web app. This will take you to a new page where you’ll need to put in a nickname for the app and then present some JavaScript code for loading the Firebase library (make sure that “Use npm” is selected—you don’t want to include a <code><script></code> element!).</p>
<p>In a React app you you will integrate Firebase directly into your source code by modifying the <strong><code>index.js</code></strong> file:</p>
<ol style="list-style-type: decimal">
<li><p>First, install and <a href="https://www.npmjs.com/package/firebase">Firebase library</a> using <code>npm</code>:</p>
<pre class="language-bash"><code><span class="token comment"># Note: do this in your app's repo (the folder with the `package.json` file)</span>
<span class="token function">npm</span> <span class="token function">install</span> firebase</code></pre></li>
<li><p>Then, copy the provided <code>import</code> statement, <code>firebaseConfig</code> variable, and <code>initializeApp()</code> function call into your <strong><code>index.js</code></strong> file. This will specify <em>which</em> Firebase project your web app should connect to whenver you call functions to access Firebase.</p>
<p>Note that you will need to paste this code <em>before</em> the call <code>ReactDOM.render()</code>. The <code>index.js</code> file will often contain such configuration data that is relevant to the <em>app</em> rather than to a specific component.</p></li>
</ol>
</div>
<div id="adding-collaborators-to-a-project" class="section level3 unnumbered">
<h3>Adding Collaborators to a Project</h3>
<p>Referencing the Firebase Web Console is vital for everyone who is working with the Firebase backend on a project. If you’re working with a group of developers, you will want to make sure that all team members have access to this console.</p>
<p>You can add additional team members to a Firebase project by selecting “Users and permissions” from the “Project Overview” gear icon:</p>
<div class="figure">
<img src="img/firebase/firebase-nav-users.png" alt="" />
<p class="caption">Users and permissions navigation</p>
</div>
<p>From there you can click on “Add Member” to add new members to the project.</p>
</div>
</div>
<div id="realtime-database" class="section level2" number="19.2">
<h2><span class="header-section-number">19.2</span> Realtime Database</h2>
<p>The Firebase web service provides a <a href="https://firebase.google.com/docs/database"><strong>realtime database</strong></a> for storing and accessing data in the cloud. You can think of this database as being a <em>single giant JSON object in the Cloud</em> that can be simultaneously accessed and modified by multiple clients—and since each client reads the same database, changes made by one user will be seen by others as <em>real-time updates</em>.</p>
<p>For example, you might have a database that is structured like:</p>
<pre class="language-json"><code><span class="token punctuation">{</span>
<span class="token property">"people"</span> <span class="token operator">:</span> <span class="token punctuation">{</span>
<span class="token property">"amit"</span> <span class="token operator">:</span> <span class="token punctuation">{</span>
<span class="token property">"age"</span> <span class="token operator">:</span> <span class="token number">35</span><span class="token punctuation">,</span>
<span class="token property">"petName"</span> <span class="token operator">:</span> <span class="token string">"Spot"</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token property">"sarah"</span> <span class="token operator">:</span> <span class="token punctuation">{</span>
<span class="token property">"age"</span> <span class="token operator">:</span> <span class="token number">42</span><span class="token punctuation">,</span>
<span class="token property">"petName"</span> <span class="token operator">:</span> <span class="token string">"Rover"</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token property">"zhang"</span> <span class="token operator">:</span> <span class="token punctuation">{</span>
<span class="token property">"age"</span> <span class="token operator">:</span> <span class="token number">13</span><span class="token punctuation">,</span>
<span class="token property">"petName"</span> <span class="token operator">:</span> <span class="token string">"Fluffy"</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>This database object has a <code>people</code> key that refers to an object, which itself contains keys that refer to individual “person” objects (each of which has an <code>age</code> and <code>petName</code> property).</p>
<p>In the Firebase Web Console (under the “Database” tab in the navigation menu), this data structure would be presented as:</p>
<div class="figure">
<img src="img/firebase/firebase-people-db.png" alt="" />
<p class="caption">A Firebase database with sample people data</p>
</div>
<ul>
<li>Note that in the Firebase Web Console you can edit this database directly: viewing, adding, editing, and deleting elements in the JSON. This is useful for debugging—both to check that your code is editing the database accurately, and to clean up any mistakes.</li>
</ul>
<p class="alert alert-warning">
Although the JSON database can have many levels of nested objects, best practice is to try and keep the structure as “flat” as possible and avoid nesting too much data. This avoids you needing to download the nested “details” for a value if you only need to know e.g., the key names. See <a href="https://firebase.google.com/docs/database/web/structure-data">Structure Your Data</a> for more details and examples.
</p>
<div id="setting-up-the-database" class="section level3 unnumbered">
<h3>Setting Up the Database</h3>
<p>In order to enable the realtime database for your project, navigate to the console page for the database and click the “Create Database” button.</p>
<p class="alert alert-warning">
Make sure you’re creating the <em>Realtime Database</em>, not the Firestore Database!
</p>
<p>After selecting your local region, you’ll be prompted to set up the <a href="firebase.html#security-rules"><strong>Security Rules</strong></a>. Choose to start in <em>test mode</em> to get started immediately; see the below section for more about security rules.</p>
<div id="security-rules" class="section level4 unnumbered">
<h4>Security Rules</h4>
<p>Because the Firebase database is just a giant JSON object in the cloud and is usable from a client-side system, technically <em>anyone</em> can access it. Each element of the JSON object is accessible via AJAX requests (which are sent via <code>firebase</code> functions).</p>
<p>In order to restrict what clients can access this information (read or write to values in the JSON), Firebase lets you define <a href="https://firebase.google.com/docs/database/security/">security rules</a> that specify what users can access which elements. For example, you can make it so that only <em>authenticated users</em> can add new entries the database, or that only specific users can update specific entries (e.g., the comments they wrote on a blog).</p>
<ul>
<li>By default, no one can access or modify the data (in <em>locked mode</em>). If you choose to start your project in <em>test mode</em>, then anyone will be able to access or modify the entire database for a limited amount of time.</li>
</ul>
<p>In order to modify or configure the security rules, navigate to the “Rules” tab of the Realtime Database’s page in the Firebase Web Console. You can modify the rules by editing the presented JSON data; remember to hit “Publish” after you’re done editing.</p>
<p>Firebase Security Rules are defined in JSON using a particular (and somewhat awkard) scheme. Basically, inside the <code>"rules"</code> property you specify a JSON tree that mirrors the structure of your database. But instead of having a value for the keys in your database, you specify an object with <code>".read"</code> and <code>".write"</code> properties. The values of these properties are boolean expressions that state whether or not the current user is able to read (access) or write (modify) that value. For more on writing rules, such as how to handle user authorization (only certain users can read/write access) or data validation (making sure all data is written of a certain type), see <a href="https://firebase.google.com/docs/database/security/">the official documentation</a>.</p>
</div>
</div>
<div id="data-references" class="section level3 unnumbered">
<h3>Data References</h3>
<p>To start working with your database, you will need to get a <strong>reference</strong> to that value in the database.</p>
<p>You begin by getting a reference to the database itself, using the <strong><code>getDatabase()</code></strong> function provided by Firebase’s database module <code>firebase/database</code>:</p>
<pre class="language-js"><code><span class="token comment">//import the function from the realtime database module</span>
<span class="token keyword">import</span> <span class="token punctuation">{</span> getDatabase <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'firebase/database'</span><span class="token punctuation">;</span>
<span class="token comment">//get a reference to the database service</span>
<span class="token keyword">const</span> db <span class="token operator">=</span> <span class="token function">getDatabase</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>Importantly, the <code>db</code> value in the example is <strong>not</strong> a copy of the data or even the database itself! It’s instead just a reference pointer to where that database lives—you can think of it more like a “URL” for the database.</p>
<ul>
<li>The <code>getDatabase()</code> function is a simple <em>singleton</em> accessor that runs in constant time; it’s best practice to call it scoped in whatever functional scope you need to refer to the database. You do not need topass it around as a prop, nor should you try to make a “top level” or global <code>db</code> variable. Just call the function again if you need to access the database from a separate scope.</li>
</ul>
<p>In order to modify any particular values in the database, you will need to get a <a href="https://firebase.google.com/docs/reference/js/database.databasereference"><strong>reference</strong></a> to that value. This is done by using the <strong><code>ref()</code></strong> function, passing in the database reference and the “path” (a string) to the data value in the database’s JSON:</p>
<pre class="language-js"><code><span class="token keyword">import</span> <span class="token punctuation">{</span> getDatabase<span class="token punctuation">,</span> ref <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'firebase/database'</span><span class="token punctuation">;</span>
<span class="token comment">//get a reference to the database service</span>
<span class="token keyword">const</span> db <span class="token operator">=</span> <span class="token function">getDatabase</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">//get reference to the "people"" property in the database</span>
<span class="token keyword">const</span> peopleRef <span class="token operator">=</span> <span class="token function">ref</span><span class="token punctuation">(</span>db<span class="token punctuation">,</span> <span class="token string">"people"</span><span class="token punctuation">)</span>
<span class="token comment">//get reference to the "sarah" property inside the "people" property in the database</span>
<span class="token comment">//similar to `database.people.sarah` using dot notation</span>
<span class="token keyword">const</span> sarahRef <span class="token operator">=</span> <span class="token function">ref</span><span class="token punctuation">(</span>db<span class="token punctuation">,</span> <span class="token string">"people/sarah"</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>Again, these reference are <strong>not</strong> the data! They are just reference pointers to where the data lives—like the “URL” for that data value.</p>
<p>The “path” to nested values in the database are written in a URI-style “path notation”, where each nested key is indicated by a slash <strong><code>/</code></strong> (rather than the <code>.</code> in dot notation as you’d normally use with JSON format). Thus <code>"people/sarah"</code> refers to the <code>sarah</code> key inside of the <code>people</code> key inside of the database; <code>"people/sarah/pet"</code> refers to the <code>pet</code> key inside the <code>sarah</code> key inside the <code>people</code> key—the spot in the database with the value <code>"Rover"</code> in the above example.</p>
<p>Since this path is just a string, you can use string concatenation to construct the path to a particular value you wish to reference (e.g., if you only want to work with the value for a particular person):</p>
<pre class="language-js"><code><span class="token comment">//variable name to access</span>
<span class="token keyword">const</span> personName <span class="token operator">=</span> <span class="token string">"Ada"</span><span class="token punctuation">;</span>
<span class="token comment">//access the "Ada" property inside of the "people" property inside the database</span>
<span class="token keyword">const</span> personOfInterestRef <span class="token operator">=</span> <span class="token function">ref</span><span class="token punctuation">(</span>db<span class="token punctuation">,</span> <span class="token string">"people/"</span><span class="token operator">+</span>personName<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>Alternatively, you can use the <strong><code>child()</code></strong> function to get a reference to a specific “child” element in the database:</p>
<pre class="language-js"><code><span class="token keyword">import</span> <span class="token punctuation">{</span> ref<span class="token punctuation">,</span> child <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'firebase/database'</span><span class="token punctuation">;</span>
<span class="token comment">//equivalent to the above example</span>
<span class="token comment">//get reference to the "people" property in the database</span>
<span class="token keyword">const</span> peopleRef <span class="token operator">=</span> <span class="token function">ref</span><span class="token punctuation">(</span>db<span class="token punctuation">,</span> <span class="token string">"people"</span><span class="token punctuation">)</span>
<span class="token comment">//get reference to the "sarah" property inside of the "people" reference'd value</span>
<span class="token keyword">const</span> sarahRef <span class="token operator">=</span> <span class="token function">child</span><span class="token punctuation">(</span>peopleRef<span class="token punctuation">,</span> <span class="token string">"sarah"</span><span class="token punctuation">)</span></code></pre>
<p>In general, you want to work with a small a subset the data as possible. Thus it’s better to get a reference to <code>"person/sarah"</code> if you’re only going to read or write to that value, rather than get a reference to the whole <code>"people"</code> and then just read/write the <code>sarah</code> key in that.</p>
</div>
<div id="writing-data" class="section level3 unnumbered">
<h3>Writing Data</h3>
<p>You can modify values in the database by using the <strong><code>set()</code></strong> function. This function takes two arguments: a <em>database reference</em>, and then the new value you want to assign to that location in the database:</p>
<pre class="language-js"><code><span class="token comment">//alias the `set` function as `firebaseSet`</span>
<span class="token keyword">import</span> <span class="token punctuation">{</span> ref<span class="token punctuation">,</span> <span class="token keyword">set</span> <span class="token keyword">as</span> firebaseSet <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'firebase/database'</span>
<span class="token comment">//get a reference to where sarah's age is stored in the database</span>
<span class="token keyword">const</span> sarahAgeRef <span class="token operator">=</span> <span class="token function">ref</span><span class="token punctuation">(</span>db<span class="token punctuation">,</span> <span class="token string">"people/sarah/age"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">//change Sarah's age to 43 (happy birthday!)</span>
<span class="token keyword">const</span> newValueForSarahAge <span class="token operator">=</span> <span class="token number">43</span><span class="token punctuation">;</span>
<span class="token comment">//assign the new value in the database</span>
<span class="token function">firebaseSet</span><span class="token punctuation">(</span>sarahRef<span class="token punctuation">,</span> newValueForSarahAge<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>This will change the value in the database at <code>"people/sarah/age"</code> to <code>43</code>.</p>
<p>Note that in this example, I use the <code>as</code> keyword to <em>alias</em> the <code>set</code> function when importing it, instead calling it <code>firebaseSet</code>. This is for clarity, as “set” is an overly generic name for a function.</p>
<p>Note that as with normal JSON objects, you can also “set” values for database entries that didn’t previously exist—you do not have to “declare” a value in the database ahead of time</p>
<pre class="language-js"><code><span class="token comment">//a reference to the people entry in the database</span>
<span class="token keyword">const</span> peopleRef <span class="token operator">=</span> <span class="token function">ref</span><span class="token punctuation">(</span>db<span class="token punctuation">,</span> <span class="token string">"people"</span><span class="token punctuation">)</span>
<span class="token comment">//a reference to a location with no currently defined value</span>
<span class="token keyword">const</span> adaRef <span class="token operator">=</span> <span class="token function">ref</span><span class="token punctuation">(</span>peopleRef<span class="token punctuation">,</span> <span class="token string">"ada"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">//set an object to that location in the database</span>
<span class="token function">firebaseSet</span><span class="token punctuation">(</span>adaRef<span class="token punctuation">,</span> <span class="token punctuation">{</span><span class="token literal-property property">age</span><span class="token operator">:</span> <span class="token string">"206"</span><span class="token punctuation">,</span> <span class="token literal-property property">pet</span><span class="token operator">:</span> <span class="token string">"Charlie"</span><span class="token punctuation">}</span><span class="token punctuation">)</span></code></pre>
<p>Firebase also provides an equivalent method <code>update()</code>, which will “merge” in changes to the existing value at a reference. This allows you to <code>update()</code> the a reference pass in an object with some properties to be modified, while existing properties are be retained (rather than having the entire value at that reference be replaced).</p>
<p>Finally, note that the <code>set()</code> method returns a <em>Promise</em>. Thus you can use <code>.then()</code> (or <code>await</code>) to execute statements after the database has updated, and you can thus catch any errors that may occur when attempting to update a value. This is especially useful for debugging, but also is good for providing user feedback.</p>
<pre class="language-js"><code><span class="token keyword">const</span> sarahPetRef <span class="token operator">=</span> <span class="token function">ref</span><span class="token punctuation">(</span>db<span class="token punctuation">,</span> <span class="token string">"people/sarah/pet"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">//change Sarah's pet</span>
<span class="token function">firebaseSet</span><span class="token punctuation">(</span>sarahPetRef<span class="token punctuation">,</span> <span class="token string">"Sparky"</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"data saved successfully!"</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">catch</span><span class="token punctuation">(</span><span class="token parameter">err</span> <span class="token operator">=></span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//log any errors for debugging</span></code></pre>
</div>
<div id="listening-for-data-changes" class="section level3 unnumbered">
<h3>Listening for Data Changes</h3>
<p>Because Firebase’s database is intended for <em>realtime</em> access (that may change over time), you read data from it and establish <em>data binding</em> by registering an <strong>event listener</strong> to listen for changes to that database. In effect, any modifications to the data causes a “database change event” which triggers your listener, allowing you to acccess the new updated data.</p>
<p>You register a database change listener by using the <strong><code>onValue()</code></strong> function. This function takes as arguments a database reference (which value you want to listen for changes to) and a callback function that will be executed in response to the event (similar to the DOM’s <code>addEventListener()</code> function):</p>
<pre class="language-js"><code><span class="token keyword">import</span> <span class="token punctuation">{</span> ref<span class="token punctuation">,</span> onValue <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">"firebase/database"</span>
<span class="token comment">//get a reference to a particular value location in the database</span>
<span class="token keyword">const</span> amitRef <span class="token operator">=</span> <span class="token function">ref</span><span class="token punctuation">(</span>db<span class="token punctuation">,</span> <span class="token string">'people/amit'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">//register a listener for changes to that value location</span>
<span class="token function">onValue</span><span class="token punctuation">(</span>amitRef<span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">snapshot</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> amitValue <span class="token operator">=</span> snapshot<span class="token punctuation">.</span><span class="token function">val</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>amitValue<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//=> e.g., { age: 35, petName: "Spot" }</span>
<span class="token comment">//can do something else with amitValue (e.g., assign to a state variable)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>The callback function will be passed as a parameter the latest <a href="https://firebase.google.com/docs/reference/js/firebase.database.DataSnapshot"><strong>snapshot</strong></a> of the data value at the listening location. This is a wrapper around the database’s JSON tree (allowing you to navigate it e.g., with <code>child()</code>). Most commonly, you will want to convert the snapshot into an actual JavaScript object by calling the <strong><code>.val()</code></strong> method on it.</p>
<p>The listener will trigger whenever any child node of the targeted refence location changes. Thus even if just <code>people/amit/pet</code> is updated, the above listener will trigger.</p>
<p>Importantly, because this listener involves network access and can trigger throughout the life of your application, in a React app you will need to register the listener inside an <em>effect hook</em>. The effect hook’s “cleanup function” will also need to remove the listener—otherwise you will have a memory leak and can get errors if your component gets removed (e.g., by changing routes). The <code>onValue()</code> function <em>returns</em> a new function that can be used to “unregister” the listener:</p>
<pre class="language-jsx"><code><span class="token keyword">function</span> <span class="token function">MyComponent</span><span class="token punctuation">(</span><span class="token parameter">props</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">//effect hook</span>
<span class="token function">useEffect</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> db <span class="token operator">=</span> <span class="token function">getDatabase</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> amitRef <span class="token operator">=</span> <span class="token function">ref</span><span class="token punctuation">(</span>db<span class="token punctuation">,</span> <span class="token string">"people/amit"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">//returns a function that will "unregister" (turn off) the listener</span>
<span class="token keyword">const</span> unregisterFunction <span class="token operator">=</span> <span class="token function">onValue</span><span class="token punctuation">(</span>amitRef<span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">snapshot</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> amitValue <span class="token operator">=</span> snapshot<span class="token punctuation">.</span><span class="token function">val</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">//...set state variable, etc...</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token comment">//cleanup function for when component is removed</span>
<span class="token keyword">function</span> <span class="token function">cleanup</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token function">unregisterFunction</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//call the unregister function</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> cleanup<span class="token punctuation">;</span> <span class="token comment">//effect hook callback returns the cleanup function</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span></code></pre>
<p>Note that it is possble to read a single value once (without needing to register a listener) by using the <code>get()</code> method. This method returns a promise that will contain the read snapshot (once it is downloaded). <em>However</em>, the Realtime Database is intended and optimized for data binding and notifications. Thus you should pretty much always be using <code>onValue()</code> to read data from the database. If you find yourself wanting to just read a single value once, you’re not thinking about the realtime database correctly!</p>
</div>
<div id="firebase-arrays" class="section level3 unnumbered">
<h3>Firebase Arrays</h3>
<p>When working with and storing data in the cloud, we often want to organize that data into lists using <em>arrays</em>. However, Firebase <strong>does not</strong> directly support support arrays: the JSON object in the sky only contains objects, not arrays! This is because Firebase needs to support <strong>concurrent access</strong>: multiple people need to be able to access the data at the same time. But since arrays are accessed by <em>index</em>, this can cause problems if two people try to modify the array at the same time.</p>
<ul>
<li>The problem is that with an array, an index number doesn’t always refer to the same element! For example, if you have an array <code>['a', 'b' 'c']</code>, then index <code>1</code> may initially refer to the <code>'b'</code>. However, if you add an element onto the beginning of the array, then suddenly that <code>1</code> index refers to the <code>'a'</code>. And so if a user was trying to modify the <code>'b'</code> before their machine was aware of the change, they may end up editing the wrong value when they ask to change the value at index <code>1</code>! This bug is an example of a <a href="https://en.wikipedia.org/wiki/Race_condition">race condition</a>, which can occur when two processes are modifying data <em>concurrently</em> (at the same time).</li>
</ul>
<!-- could put code version of example ?? -->
<p>To avoid this problem, Firebase treats all data structures as Objects, so that each value in the JSON tree has a <em>unique</em> key. That way each client will always be modifying the value they expect. However, Firebase does offer a way that you can treat Objects as arrays, in the form of a <strong><code>push()</code></strong>(<a href="https://firebase.google.com/docs/reference/js/firebase.database.Reference#push" class="uri">https://firebase.google.com/docs/reference/js/firebase.database.Reference#push</a>) function that will add a value to an object with an <strong>auto-generated key</strong>.</p>
<pre class="language-js"><code><span class="token keyword">import</span> <span class="token punctuation">{</span> getDatabase<span class="token punctuation">,</span> ref<span class="token punctuation">,</span> push <span class="token keyword">as</span> firebasePush <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'firebase/database'</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> db <span class="token operator">=</span> getDatabase<span class="token punctuation">;</span>
<span class="token keyword">const</span> tasksRef <span class="token operator">=</span> <span class="token function">ref</span><span class="token punctuation">(</span>db<span class="token punctuation">,</span> <span class="token string">"tasks"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//an object of tasks</span>
<span class="token function">firebasePush</span><span class="token punctuation">(</span>taskRef<span class="token punctuation">,</span> <span class="token punctuation">{</span><span class="token literal-property property">description</span><span class="token operator">:</span><span class="token string">'First things first'</span><span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token comment">//add one task</span>
<span class="token function">firebasePush</span><span class="token punctuation">(</span>taskRef<span class="token punctuation">,</span> <span class="token punctuation">{</span><span class="token literal-property property">description</span><span class="token operator">:</span><span class="token string">'Next things next'</span><span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token comment">//add another task</span></code></pre>
<p>This will produce a database with a structure:</p>
<pre class="language-json"><code><span class="token punctuation">{</span>
<span class="token property">"tasks"</span> <span class="token operator">:</span> <span class="token punctuation">{</span>
<span class="token property">"-KyxgJhKOVeAj2ibPxrO"</span> <span class="token operator">:</span> <span class="token punctuation">{</span>
<span class="token property">"description"</span> <span class="token operator">:</span> <span class="token string">"First things first"</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token property">"-KyxgMDJueu17348NxDF"</span> <span class="token operator">:</span> <span class="token punctuation">{</span>
<span class="token property">"description"</span> <span class="token operator">:</span> <span class="token string">"Next things next"</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>Notice how the <code>tasks</code> property is an Object (even though we “pushed” elements into it), and each “task” is assigned an auto-generated key (based on the timestamp it was pushed). You can still interact with <code>tasks</code> as if it were an array-like list, but instead of using a value from <code>0</code> to <code>length</code> as the index, you’ll use a generated “key” as the index.</p>
<p class="alert alert-warning">
<strong>Always</strong> use the <code>push()</code> function to have Firebase automatically manage data arrays for you. <strong>Never</strong> try to manually create an “array” by giving values keys “0”, “1”, “2” etc.
</p>
<p>Firebase <em>snapshots</em> do support a <code>forEach()</code> function that you can use to iterate through their elements, allowing you to loop through the elements in an array. However, if you want to do something more complex (like <code>map()</code>, <code>filter()</code>, or <code>reduce()</code>), you need an actual array. The best way to get this is use call <code>Objects.keys()</code> on the <code>snapshot.val()</code> in order to get an array of the keys, and then you can iterate/map those keys into an array of values (accessing each element in the “array” using bracket notation).</p>
<pre class="language-js"><code><span class="token comment">//`tasksSnapshot` is a snapshot of the `tasks` "array"</span>
<span class="token keyword">const</span> allTasksObject <span class="token operator">=</span> tasksSnapshot<span class="token punctuation">.</span><span class="token function">val</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//convert snapshot to value</span>
<span class="token comment">//an array of the keys in the object ["-KyxgJhKOVeAj2ibPxrO", "-KyxgMDJueu17348NxDF"]</span>
<span class="token keyword">const</span> allTasksKeys <span class="token operator">=</span> Object<span class="token punctuation">.</span><span class="token function">keys</span><span class="token punctuation">(</span>allTasksObject<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">//map array of keys into array of tasks</span>
<span class="token keyword">const</span> allTasksArray <span class="token operator">=</span> allTasksKeys<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">key</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> singleTaskCopy <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token operator">...</span>allTasksObject<span class="token punctuation">[</span>key<span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token comment">//copy element at that key</span>
singleTaskCopy<span class="token punctuation">.</span>key <span class="token operator">=</span> key<span class="token punctuation">;</span> <span class="token comment">//locally save the key string as an "id" for later</span>
<span class="token keyword">return</span> singleTaskCopy<span class="token punctuation">;</span> <span class="token comment">//the transformed object to store in the array</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
allTasksArray<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">taskObject</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token operator">...</span> <span class="token punctuation">}</span><span class="token punctuation">)</span></code></pre>
<p>Note that when looping through an “array”, each element is handled separately from its key (the same way that a <code>forEach()</code> loop lets you work with array elements separately from their index). But since you may need that key as an identifier in order to <code>ref()</code> and modify the JSON element later, you should make sure that you “save” the key in the object as you processing it as an additional local property. This won’t modify the value in the database, just the local variable that your code is working with. <em>Don’t lose your key!</em>.</p>
</div>
</div>
<div id="user-authentication" class="section level2" number="19.3">
<h2><span class="header-section-number">19.3</span> User Authentication</h2>
<p>Firebase provides the ability to <strong>authenticate</strong> users: to let people sign up for you application and then to check that they are who they say (e.g., have provided the right password). Firebase supports multiple different forms of authentication: users can sign up with an email and password, log in with a social media service such as Google or Facebook, or even authenticate “anonymously” (so you can at least keep track of different people even if you don’t know who they are).</p>
<p>In order to support user authentication, you will need to enable this feature in the Firebase Web Console. Click on the “Authentication” link in the side navigation menu’s Build capetgory to go to the authentication management page, then choose “Get started”. Under the “Sign-In Method” tab, you can choose what forms of authentication you wish to enable.</p>
<ul>
<li><p>For example, click on the “Email/Password” option, and then flip the switch to “Enable” that method. Be sure and Save your changes!</p></li>
<li><p>Each different sign-in method uses what is called a “Provider”—a service that provides the information about whether the user is who they say. Firebase’s email/password check is a possible Provider; Google is a possible Provider; etc. You can enable multiple different Providers, each of which will be able to authenticate users (i.e., letting them sign in with the relevat credentials).</p></li>
</ul>
<p>Note that you will be able to use this page to see and manage users who have signed up with your Firebase project. This is where you can see if uses have successfully been created, look up their <strong>User UID</strong> for debugging, or delete users from the project:</p>
<div class="figure">
<img src="img/firebase/firebase-users.png" alt="" />
<p class="caption">Firebase users as presented in the authentication web console</p>
</div>
<div id="signing-in-with-firebaseui" class="section level3 unnumbered">
<h3>Signing In with FirebaseUI</h3>
<p>It is possible to call functions provided by Firebase in order to create and log in users. However, this would require you to implement the “log in form” on your own—and would only easily support the Email/Password authentication option.</p>
<p>Instead, a nicer approach is to use the <a href="https://firebase.google.com/docs/auth/web/firebaseui"><strong>FireabaseUI</strong></a> library, also managed by Firebase. This library provides a set of predefined UI elements like a “login form”, including ones which will support different authentication methods.</p>
<div class="figure">
<img src="img/firebase/firebaseui-example.png" alt="" />
<p class="caption">Example of FirebaseUI authentication</p>
</div>
<p>There are different FirebaseUI libraries for different platforms; previously for React you would use <a href="https://github.com/firebase/firebaseui-web-react"><code>firebaseui-web-react</code></a>. However, as of November 2022 this library has not been updated to work with the latest version of React (React 18), and appears to have been been abandoned rather than <a href="https://github.com/firebase/firebaseui-web-react/pull/173">applying the needed fix</a>. There are two possible workarounds to this:</p>
<ol style="list-style-type: decimal">
<li><p>You can install a version of the library updated by <a href="https://github.com/gvillenave">Gabriel Villenave</a> (which hasn’t been accepted as a pull request yet):</p>
<pre class="language-bash"><code><span class="token comment"># install library on the command line</span>
<span class="token function">npm</span> <span class="token function">install</span> https://gitpkg.now.sh/gvillenave/firebaseui-web-react/dist</code></pre>
<p>Confirm that your <code>package.json</code> file has the correct dependency listed:</p>
<pre><code>"react-firebaseui": "https://gitpkg.now.sh/gvillenave/firebaseui-web-react/dist"</code></pre></li>
<li><p>You can install the non-React version of the library (<code>firebaseui</code>), and then define the needed Component (<code>StyledFirebaseUI</code>) manually:</p>
<pre class="language-bash"><code><span class="token function">npm</span> <span class="token function">install</span> firebaseui</code></pre>
<p>Create the <code>StyledFirebaseAuth.txs</code> file defined <a href="https://github.com/firebase/firebaseui-web-react/pull/173#issuecomment-1224404146">in this comment post</a>.</p></li>
</ol>
<p>The React FirebaseUI library provides a Component called <code><StyledFirebaseAuth></code>, which you can render in your page like any other Component. You can think of this Component as the “login form”. A complete example of how this Component is used can be found below, following by an explanation.</p>
<pre class="language-jsx"><code><span class="token comment">//import auth functions and variables from Firebase</span>
<span class="token keyword">import</span> <span class="token punctuation">{</span> getAuth<span class="token punctuation">,</span> EmailAuthProvider<span class="token punctuation">,</span> GoogleAuthProvider <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'firebase/auth'</span>
<span class="token comment">//import the component -- pick one!</span>
<span class="token keyword">import</span> StyledFirebaseAuth <span class="token keyword">from</span> <span class="token string">'react-firebaseui/StyledFirebaseAuth'</span><span class="token punctuation">;</span> <span class="token comment">//install option 1</span>
<span class="token keyword">import</span> StyledFirebaseAuth <span class="token keyword">from</span> <span class="token string">'./StyledFirebaseAuth'</span><span class="token punctuation">;</span> <span class="token comment">//install option 2</span>
<span class="token comment">//an object of configuration values</span>
<span class="token keyword">const</span> firebaseUIConfig <span class="token operator">=</span> <span class="token punctuation">{</span>
<span class="token literal-property property">signInOptions</span><span class="token operator">:</span> <span class="token punctuation">[</span> <span class="token comment">//array of sign in options supported</span>
<span class="token comment">//array can include just "Provider IDs", or objects with the IDs and options</span>
GoogleAuthProvider<span class="token punctuation">.</span><span class="token constant">PROVIDER_ID</span><span class="token punctuation">,</span>
<span class="token punctuation">{</span> <span class="token literal-property property">provider</span><span class="token operator">:</span> EmailAuthProvider<span class="token punctuation">.</span><span class="token constant">PROVIDER_ID</span><span class="token punctuation">,</span> <span class="token literal-property property">requiredDisplayName</span><span class="token operator">:</span> <span class="token boolean">true</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">]</span><span class="token punctuation">,</span>
<span class="token literal-property property">signInFlow</span><span class="token operator">:</span> <span class="token string">'popup'</span><span class="token punctuation">,</span> <span class="token comment">//don't redirect to authenticate</span>
<span class="token literal-property property">credentialHelper</span><span class="token operator">:</span> <span class="token string">'none'</span><span class="token punctuation">,</span> <span class="token comment">//don't show the email account chooser</span>
<span class="token literal-property property">callbacks</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token comment">//"lifecycle" callbacks</span>
<span class="token function-variable function">signInSuccessWithAuthResult</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span> <span class="token comment">//don't redirect after authentication</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token comment">//the React compnent to render</span>
<span class="token keyword">function</span> <span class="token function">MySignInScreen</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> auth <span class="token operator">=</span> <span class="token function">getAuth</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//access the "authenticator"</span>
<span class="token keyword">return</span> <span class="token punctuation">(</span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>h1</span><span class="token punctuation">></span></span>My App<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>h1</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>p</span><span class="token punctuation">></span></span>Please sign<span class="token operator">-</span><span class="token keyword">in</span><span class="token operator">:</span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>p</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span><span class="token class-name">StyledFirebaseAuth</span></span> <span class="token attr-name">uiConfig</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span>firebaseUIConfig<span class="token punctuation">}</span></span> <span class="token attr-name">firebaseAuth</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span>auth<span class="token punctuation">}</span></span> <span class="token punctuation">/></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>There are a few steps to using this Component:</p>
<ul>
<li><p>The <code><StyledFirebaseAuth></code> requires a <code>uiConfig</code> prop, which is an object containing configuration values for that login form (the object has specific properties which correspond to configuratoin options). The config object is usually defined as a global constant.</p>
<p>The most important configuration option is the <code>signInOptions</code>, listing the different authentication providers supported (what options should show up in the login form). The IDs for these providers are imported from the <code>'firebase/auth'</code> library—though they are numeric values, not functions.</p>
<p>Other common/useful options are shown in the example; for a complete list of options see <a href="https://github.com/firebase/firebaseui-web#configuration">the firebaseui-web documentation</a>.</p></li>
<li><p>The <code><StyledFirebaseAuth></code> also requires a <code>firebaseAuth</code> prop, which is a reference to the “authenticator” service—what will handle the process of the user logging in and out. You can get access to this value via the <strong><code>getAuth()</code></strong> function provided by <code>'firebase/auth'</code> (similar to how you get access to the Realtime Database via the <code>getDatabase()</code> function).</p>
<p>Note that as with <code>getDatabase()</code> the authenticator is a <em>singleton</em> value—you can call <code>getAuth()</code> from multiple modules/files/scopes without concern. You do not need to pass it around as a prop or declare it as a “top-level” constant.</p></li>
</ul>
<p>With this Component, users will be able to “log in”, though see the <a href="firebase.html#managing-the-user">Managing the User</a> section below. You will be able to see a list of users who have connected to your app in the Firebase Web Console. Note in particular that you can see their <em>uid</em> (unique identifier), which is what is used to distinguish between users. (You can’t use emails as identifiers, because someone who logs in with Facebook won’t provide their email address!).</p>
<p class="alert alert-info">
<strong>Pro-tip:</strong> You don’t need to come up with real email addresses for testing. Try using <code>[email protected]</code>, <code>[email protected]</code>, <code>[email protected]</code>, etc. Similarly, <code>password</code> works fine for testing passwords (though you should never do that in real life!)
</p>
<p>The Firebase Web Console will provide a view of the “user list”—but importantly, this is <em>not the same as the Realtime Database</em>. The user list holds <em>very</em> limited information: the authentication provider, a “display name”, and possibly a “photo url” (e.g., where to find an avatar image). But you cannot store any additional information in the “user database”—not profile images, not preferred names or pronouns used, not favorite fish. Any user-specific information will need to be stored in the Realtime Database instead, usually using a “key” that is the user’s <code>uid</code>. For example, your Realtime Database might store information like:</p>
<pre class="language-json"><code><span class="token punctuation">{</span>
<span class="token property">"userData"</span> <span class="token operator">:</span> <span class="token punctuation">{</span>
<span class="token property">"userId1"</span> <span class="token operator">:</span> <span class="token punctuation">{</span>
<span class="token property">"pronouns"</span> <span class="token operator">:</span> <span class="token string">"they/them"</span><span class="token punctuation">,</span>
<span class="token property">"favoriteFish"</span> <span class="token operator">:</span> <span class="token string">"sea bass"</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token property">"userId2"</span> <span class="token operator">:</span> <span class="token punctuation">{</span>
<span class="token property">"pronouns"</span> <span class="token operator">:</span> <span class="token string">"he/him"</span><span class="token punctuation">,</span>
<span class="token property">"favoriteFish"</span> <span class="token operator">:</span> <span class="token string">"cuttle fish"</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>You can then access the user’s data using the same process as any other data in the realtime database, listening to the reference <code>"userData/"+userId</code>.</p>
<p>In order to sign out a user, you can use another built-in Firebase function: <strong><code>signOut()</code></strong>:</p>
<pre class="language-js"><code><span class="token keyword">import</span> <span class="token punctuation">{</span> getAuth<span class="token punctuation">,</span> signOut <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'firebase/auth'</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> auth <span class="token operator">=</span> <span class="token function">getAuth</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">signOut</span><span class="token punctuation">(</span>auth<span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">catch</span><span class="token punctuation">(</span><span class="token parameter">err</span> <span class="token operator">=></span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//log any errors for debugging</span></code></pre>
<p>Note that the <code>signOut()</code> method returns a Promise, so you can <code>.catch()</code> and display any errors.</p>
</div>
<div id="managing-the-user" class="section level3 unnumbered">
<h3>Managing the User</h3>
<p>Although FirebaseUI will log in a user, you will need to do further work in order for your app to know who that logged in user is.</p>
<p>The <em>authenticator</em> (from <code>getAuth()</code>) will keep track of which Firebase User is currently logged in—and this information persists <a href="https://firebase.google.com/docs/auth/web/auth-state-persistence">even after the browser is closed</a>. This means that every time you reload the page, the authenticator will automatically perform the authentication and “re-login” the user.</p>
<p>The recommended way to <a href="https://firebase.google.com/docs/auth/web/manage-users#get_the_currently_signed-in_user">determine who is currently logged</a> in is to register an <em>event listener</em> to listen for events that occur when the “state” of the authentication changes (e.g., a user logs in or logs out). This event will occur when the page first loads and Firebase determines that a user has previously signed up (the “initial state” is set), or when a user logs in or out. You can register this listener by using Firebase’s <strong><code>onAuthStateChanged()</code></strong> function:</p>
<pre class="language-js"><code><span class="token comment">//import functions</span>
<span class="token keyword">import</span> <span class="token punctuation">{</span> getAuth<span class="token punctuation">,</span> onAuthStateChanged <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'firebase/auth'</span>
<span class="token keyword">const</span> auth <span class="token operator">=</span> <span class="token function">getAuth</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">onAuthStateChanged</span><span class="token punctuation">(</span>auth<span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">firebaseUser</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">if</span><span class="token punctuation">(</span>firebaseUser<span class="token punctuation">)</span><span class="token punctuation">{</span> <span class="token comment">//firebaseUser defined: is logged in</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'logged in'</span><span class="token punctuation">,</span> firebaseUser<span class="token punctuation">.</span>displayName<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">//do something with firebaseUser (e.g. assign to a state variable)</span>
<span class="token punctuation">}</span>
<span class="token keyword">else</span> <span class="token punctuation">{</span> <span class="token comment">//firebaseUser is undefined: is not logged in</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'logged out'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>The <code>onAuthStateChanged()</code> function takes in two arguments: the authenticator, and a callback function that will be executed whenever the “authentication state” changes (e.g., whenever the user logs in or out). The callback function will be passed an object representing the <a href="https://firebase.google.com/docs/reference/js/firebase.User">“Firebase User”</a>. This object contains properties about the user, including:</p>
<ul>
<li><code>uid</code>, which is the <em>unique id</em> for the user</li>
<li><code>displayName</code>, which is the user’s provider-independent displayable name</li>
</ul>
<p>The most common practice is to take this passed in object and assign it to a more global variable, such as a state variable in a React component (e.g., <code>setCurrentUser(firebaseUser)</code>).</p>
<p>If the user “logged out”, then the passed in <code>firebaseUser</code> value will be <code>null</code>; this information can also be saved to the React state variable.</p>
<p>Importantly, because this listener involves network access and can trigger throughout the life of your application, in a React app you will need to register the listener inside an <em>effect hook</em>. The effect hook’s “cleanup function” will also need to remove the listener. The <code>onAuthStateChanged()</code> function <em>returns</em> a new function that can be used to “unregister” the listener:</p>
<pre class="language-jsx"><code><span class="token keyword">function</span> <span class="token function">MyComponent</span><span class="token punctuation">(</span><span class="token parameter">props</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">//effect hook</span>
<span class="token function">useEffect</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> auth <span class="token operator">=</span> <span class="token function">getAuth</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">//returns a function that will "unregister" (turn off) the listener</span>
<span class="token keyword">const</span> unregisterFunction <span class="token operator">=</span> <span class="token function">onAuthStateChanged</span><span class="token punctuation">(</span>auth<span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">firebaseUser</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token comment">//handle user state change</span>
<span class="token keyword">if</span><span class="token punctuation">(</span>firebaseUser<span class="token punctuation">)</span><span class="token punctuation">{</span>
<span class="token comment">//...</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token comment">//cleanup function for when component is removed</span>
<span class="token keyword">function</span> <span class="token function">cleanup</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token function">unregisterFunction</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//call the unregister function</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> cleanup<span class="token punctuation">;</span> <span class="token comment">//effect hook callback returns the cleanup function</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span></code></pre>
<div id="firebase-react-hooks" class="section level4 unnumbered">
<h4>Firebase React Hooks</h4>
<p>In React systems it is common to render different content depending on whether the user is logged in. This could be done with conditional rendering, or with a “protected route” as described in <a href="client-side-routing.html#redirecting">Client-Side Routing</a>.</p>
<p>However, it takes a few seconds for Firebase to authenticate a user when a page first loads. Thus your conditional rendering will often need to handle 3 cases: when a user is logged in, when a user is not logged in, and when the user status is “loading” and the app hasn’t finished checking yet.</p>
<p>While there are some cludgy workarounds (e.g., use a special value for your state to indicate that a user is “loading”), this is a common enough situation that you can use solutions implemented by other people. One such option is the <a href="https://github.com/CSFrequency/react-firebase-hooks"><code>firebase-react-hooks</code></a> library. This library provides a simple hook (like <code>useState</code> or <code>useParams</code>) that lets you access the user status. In particular, the <code>useAuthState</code> hook will implement the authentication state listener for you:</p>
<pre class="language-jsx"><code><span class="token keyword">import</span> <span class="token punctuation">{</span> getAuth <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'firebase/auth'</span><span class="token punctuation">;</span>