-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathinteractive-react.html
More file actions
1040 lines (976 loc) · 131 KB
/
interactive-react.html
File metadata and controls
1040 lines (976 loc) · 131 KB
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 16 Interactive React | 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 16 Interactive React | 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 16 Interactive React | 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-03-10" />
<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="react.html"/>
<link rel="next" href="client-side-routing.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/fuse.js@6.4.6/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="interactive-react" class="section level1" number="16">
<h1><span class="header-section-number">Chapter 16</span> Interactive React</h1>
<p>This chapter discussed how websites built using the React library can be made interactive, with Components that render different content in response to user actions. Specifically, it details how to idiomatically handle <em>events</em>, store dynamic information in a Component’s <em>state</em> using <em>hooks</em>, as well as perform some specific common interactions (such as using forms and downloading data)</p>
<div id="handling-events-in-react" class="section level2" number="16.1">
<h2><span class="header-section-number">16.1</span> Handling Events in React</h2>
<p>You can handle user interaction in React in the same way you would <a href="dom.html#listening-for-events">using the DOM or jQuery</a>: you register an <em>event listener</em> and specify a <em>callback function</em> to execute when that event occurs.</p>
<p>In React, you register event listeners by specifying a React-specific attribute on an element. The attribute is generally named with the word <strong><code>on</code></strong> followed by the name of the event you want to respond to in <em>camelCase</em> format. For example, <code>onClick</code> registers a listener for <code>click</code> events, <code>onMouseOver</code> for <code>mouseover</code> events, and so on. You can see the full list of supported event handling attributes in the documentation for <a href="https://reactjs.org/docs/events.html#supported-events">synthetic events</a>. The attribute should be assigned a value that is a reference to a <em>callback function</em> (specified as an inline expression).</p>
<pre class="language-jsx"><code><span class="token comment">//A component representing a button that logs a message when clicked</span>
<span class="token keyword">function</span> <span class="token function">MyButton</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">//A function to call when clicked. The name is conventional, but arbitrary.</span>
<span class="token comment">//The callback will be passed the DOM event (just like with DOM callbacks)</span>
<span class="token keyword">const</span> <span class="token function-variable function">handleClick</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">event</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><span class="token string">"clicky clicky"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">//make a button with an `onClick` attribute!</span>
<span class="token comment">//this "registers" the listener and sets the callback</span>
<span class="token keyword">return</span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>button</span> <span class="token attr-name">onClick</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span>handleClick<span class="token punctuation">}</span></span><span class="token punctuation">></span></span>Click me<span class="token operator">!</span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>button</span><span class="token punctuation">></span></span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>This component renders a <code><button></code> in the DOM with a registered click event. Clicking on that DOM element will cause the <code>handleClick</code> function to be executed.</p>
<p>For readability, the above example specifies the callback function as a separate function (defined inside of the component—so yes, a function created inside of a function)! Note that it is more common to define nested callbacks using arrow functions:</p>
<pre class="language-js"><code><span class="token keyword">const</span> <span class="token function-variable function">handleClick</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">event</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'clicky clicky'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>You can also specify a callback function inline in the JSX, though this can quickly get messy and hard to read with complex event handling, so is not recommended.</p>
<pre class="language-jsx"><code><span class="token keyword">function</span> <span class="token function">MyButton</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>button</span> <span class="token attr-name">onClick</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span><span class="token punctuation">(</span><span class="token parameter">evt</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">"clicky clicky"</span><span class="token punctuation">)</span><span class="token punctuation">}</span></span><span class="token punctuation">/></span></span>
<span class="token punctuation">}</span></code></pre>
<p>Importantly, you can only register events on React elements (HTML elements like <code><button></code>, that are named with lowercase letters), not on Components. If you tried to specify a <code><MyButton onClick={callback}></code>, you would be passing a <em>prop</em> that just happened to be called <code>onClick</code>, but otherwise has no special meaning!</p>
<p class="alert alert-warning">
Although functionally similar, React event handling attributes are <strong>NOT</strong> the same as HTML event handles—React’s <code>onClick</code> is different from HTML’s <code>onclick</code>. The React attributes are specialized to work within the React event system. In the end, they’re similar to a JSX-based syntactic shortcut for using <code>addEventListener()</code>, so we aren’t actually mixing concerns more!
</p>
</div>
<div id="state-and-hooks" class="section level2" number="16.2">
<h2><span class="header-section-number">16.2</span> State and Hooks</h2>
<p>The previous section describes how to respond to user-generated events, but in order for the page to be interactive you need to be able to manipulate its rendered content when that event occurs.
For example, you could click on a button and show how many times it was pressed, select a table column to sort the data by that feature, or select a component in order to show an entirely different “page” of content (see <a href="client-side-routing.html#client-side-routing">Chapter 19</a>).</p>
<p>To achieve these effects, a component will need to keep track of its state or situation—the number on the counter, how the table is sorted, or which “page” is being shown. In React, a component’s <strong>state</strong> represents internal, dynamic information about how that Component should be rendered. The state contains data that <em>changes over time</em> (and <em>only</em> such information—if the value won’t change for that instance of a component, it shouldn’t be part of the state!). Moreover, whenever the state is changed, a React component will automatically “rerender”—the component will be “rerun” and the new, updated DOM elements returned will be displayed on the screen (replacing the previously rendered version). In short: changing the state will “refresh” the component!</p>
<!-- new stuff: Hooks! -->
<p>State can be specified for a function component by using a <em>state hook</em>. <a href="https://reactjs.org/docs/hooks-intro.html"><strong>Hooks</strong></a> are
functions provided by React that let you “hook into” the framework’s rendering and displaying processes. The state hook in particular lets you hook into the state of a component, specifying what values should be “tracked” and should cause the component to rerender.</p>
<ul>
<li><p>Hooks were introduced with React v16.8 (October 2018), and thus are the “new” current way of handling state. For details on older techniques (which require using <em>class components</em>), see <a href="class-components.html#state-in-class-components"><em>State in Class Components</em></a>.</p></li>
<li><p>Fun fact: hooks are basically an example of <a href="https://en.wikipedia.org/wiki/Mixin"><em>mixins</em></a>, which are an object-oriented technique for including/injecting data or behavior in a class without needing to inherit that behavior from a parent class.</p></li>
</ul>
<p>The <a href="https://reactjs.org/docs/hooks-state.html"><strong>state hook</strong></a> is a function provided by React called <strong><code>useState()</code></strong>. This function will need to be imported from the React library (note that it is a <em>named export</em> so should be imported as such):</p>
<pre class="language-js"><code><span class="token comment">//import the state hook function</span>
<span class="token keyword">import</span> React<span class="token punctuation">,</span> <span class="token punctuation">{</span> useState <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'react'</span><span class="token punctuation">;</span></code></pre>
<p>The <code>useState()</code> function is then called within the component function (usually at the top of the function so that the resulting variables will be available to use):</p>
<pre class="language-jsx"><code><span class="token keyword">function</span> <span class="token function">CountingButton</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">//Define a `count` state variable, initially 0</span>
<span class="token keyword">const</span> <span class="token punctuation">[</span>count<span class="token punctuation">,</span> setCount<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">useState</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">//an event handling callback</span>
<span class="token keyword">const</span> <span class="token function-variable function">handleClick</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">event</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token function">setCount</span><span class="token punctuation">(</span>count<span class="token operator">+</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//update the state to be a new value</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> <span class="token punctuation">(</span>
<span class="token punctuation">{</span> <span class="token comment">/* a button with the event handler that displays the state variable */</span><span class="token punctuation">}</span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>button</span> <span class="token attr-name">onClick</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span>handleClick<span class="token punctuation">}</span></span><span class="token punctuation">></span></span>You clicked me <span class="token punctuation">{</span>count<span class="token punctuation">}</span> times<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>button</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>Calling the <code>useState()</code> function creates a “state variable”—a value that will be tracked and stored between calls to render/rerender the component. You can almost think of a state variable as like an “instance variable” for the function (and indeed, state is stored in object instance variables).</p>
<ul>
<li><p>The <code>useState()</code> function is passed the initial starting value for the state variable. In above example, the <code>count</code> state variable will be initialized as <code>0</code>.</p></li>
<li><p>The <code>useState()</code> function returns an <em>array of two values</em>: the first is the current value of the state (e.g., what it was initialized as), and the second is a function used to modify that particular state variable (a “setter” or mutator). By convention, you use <a href="es6.html#destructuring">array destructuring</a> to assign these two values to two separate variables in a single operation. Thus the above line calling <code>useState()</code> can be read as a shorthand for:</p>
<pre class="language-js"><code><span class="token keyword">const</span> hookArray <span class="token operator">=</span> <span class="token function">useState</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//the function returns an array of 2 values</span>
<span class="token keyword">const</span> count <span class="token operator">=</span> hookArray<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token comment">//assign the 1st elem (a value) to `count`</span>
<span class="token keyword">const</span> setCount <span class="token operator">=</span> hookArray<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token comment">//assign the 2nd elem (a function) to `setCount`</span></code></pre>
<p>Importantly, there is nothing magical about the names of the variables that the <code>useState()</code> result is assigned to. It could just as well have been written:</p>
<pre class="language-js"><code><span class="token keyword">const</span> <span class="token punctuation">[</span>countVariable<span class="token punctuation">,</span> functionToUpdateCount<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">useState</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span></code></pre>
<p>Because the function is a “setter” it’s usually named as such (<code>setVARIABLE</code>), but this is not required. It’s just a function; you can name it whatever you want.</p></li>
</ul>
<p>Because the current state value is assigned to a regular variable (e.g., <code>count</code> in the above example), you can use it anywhere you would use a variable—such as in an inline expression to display the value. Note that if the value isn’t actually used in the rendered DOM in any way (directly or indirectly), it probably shouldn’t be part of the state!</p>
<div id="updating-state" class="section level3 unnumbered">
<h3>Updating State</h3>
<p>It’s not possible to change the value of a state variable directly (e.g,. you can’t do <code>count = count +1</code>)—that’s why the variable is declared as <code>const</code>! Instead, you need to use the “set state” function that was created (e.g., <code>setCount()</code> in the above example). This function will take as an argument the new value to assign to the state variable (overwriting the previous value).</p>
<p>When the set state function is called, not only will it change the value of the state variable, but it will also “rerender” the component—it will cause the component function to be called again, returning a new set of DOM elements to be shown on the screen. These DOM elements will replace the previously rendered version of the component; React merges these changes into the page’s DOM in a highly efficiency manner, changing only the elements that have actually updated—this is what makes React so effective for large scale systems.</p>
<ul>
<li>This is one of the trickier parts to remember in React: when you call a set state function, it will cause your component function to “re-run”—which means that any logic will execute for a second time (though now the “current” value of the state variable will be updated, rather than the initial value passed into <code>useState</code>).</li>
</ul>
<p class="alert alert-danger">
Never call a set state function directly from inside of your component function; only in callbacks (such as for event handling). Calling <code>setCount()</code> directly would cause an infinite recursive loop. Component functions must remain “pure” with no side effects.
</p>
<p>Moreover, set state functions are <a href="https://reactjs.org/docs/state-and-lifecycle.html#state-updates-may-be-asynchronous"><em>asynchronous</em></a>. Calling the function only sends a “request” to update the state; it doesn’t happen immediately. This is because React will “batch” multiple requests to update the state of components (and so to rerender them) together—that way if your app needs to make lots of small changes at the same time, React only needs to regenerate the DOM once, providing a significant performance boost.</p>
<pre class="language-jsx"><code><span class="token comment">//An Component with a callback that doesn't handle asynchronous state changes</span>
<span class="token keyword">function</span> <span class="token function">CounterWithError</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 keyword">const</span> <span class="token punctuation">[</span>count<span class="token punctuation">,</span> setCount<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">useState</span><span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">)</span> <span class="token comment">//initial value of 3</span>
<span class="token keyword">const</span> <span class="token function-variable function">handleClick</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">event</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token function">setCount</span><span class="token punctuation">(</span><span class="token number">4</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//change `count` to 4</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>count<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//will output "3"; state has not changed yet!</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>In this example, because <code>setCount()</code> is asynchronous, you can’t immediately access the updated state variable after calling the function. You instead need to wait for the component to “rerender”—when the component’s DOM is regenerated, it will use the updated value. If you want to see that value, log it out right before you return the DOM (not inside of the click event handler).</p>
<p>It is possible to have multiple state variables, each declared with a different call to <code>useState()</code>:</p>
<pre class="language-jsx"><code><span class="token comment">//Example from React documentation</span>
<span class="token keyword">function</span> <span class="token function">ExampleWithManyStates</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">//Declare multiple state variables!</span>
<span class="token keyword">const</span> <span class="token punctuation">[</span>age<span class="token punctuation">,</span> setAge<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">useState</span><span class="token punctuation">(</span><span class="token number">42</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token punctuation">[</span>fruit<span class="token punctuation">,</span> setFruit<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">useState</span><span class="token punctuation">(</span><span class="token string">'banana'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token punctuation">[</span>todos<span class="token punctuation">,</span> setTodos<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">useState</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">{</span> <span class="token literal-property property">text</span><span class="token operator">:</span> <span class="token string">'Learn Hooks'</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>While it’s possible for a single state variable to contain complex values (objects and arrays, as in the <code>todos</code> variable above), it’s often cleaner to use multiple different state variables—that way React needs to change as little data as possible when you wish to update a variable.</p>
<p>Importantly, you need to pass a <em>new value</em> into the set state function in order for it to actually update the state and rerender the component. Just changing a value inside of an existing object won’t work:</p>
<pre class="language-js"><code><span class="token keyword">function</span> <span class="token function">TodoListWithError</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">//a state value that is an array of objects</span>
<span class="token keyword">const</span> <span class="token punctuation">[</span>todos<span class="token punctuation">,</span> setTodos<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">useState</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">{</span> <span class="token literal-property property">text</span><span class="token operator">:</span> <span class="token string">'Learn Hooks'</span> <span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token function-variable function">handleClick</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">event</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
todos<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>text <span class="token operator">=</span> <span class="token string">"Fix bugs"</span><span class="token punctuation">;</span> <span class="token comment">//modify the object but don't make a new one</span>
<span class="token function">setTodos</span><span class="token punctuation">(</span>todos<span class="token punctuation">)</span> <span class="token comment">//This won't work!</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>In the above example, changing a property of the <code>todos</code> array-of-objects doesn’t actually change the value. This when you call <code>setTodos(todos)</code>, React thinks that nothing has updated (it doesn’t do a deep inspection of the object) so doesn’t update anything. Instead, you’ll need to create a <em>new copy</em> of the array or object, and then pass that new value into the set state function:</p>
<pre class="language-jsx"><code><span class="token keyword">function</span> <span class="token function">TodoList</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">//a state value that is an array of objects</span>
<span class="token keyword">const</span> <span class="token punctuation">[</span>todos<span class="token punctuation">,</span> setTodos<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">useState</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">{</span> <span class="token literal-property property">text</span><span class="token operator">:</span> <span class="token string">'Learn Hooks'</span> <span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token function-variable function">handleClick</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">event</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token comment">//create a copy of the array using the `map()` function</span>
<span class="token keyword">const</span> todosCopy <span class="token operator">=</span> todos<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">todoObject<span class="token punctuation">,</span> index</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>index <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">//transform objects if needed</span>
todoObject<span class="token punctuation">.</span>text <span class="token operator">=</span> <span class="token string">"Fix bugs"</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> todoObject<span class="token punctuation">;</span> <span class="token comment">//return object to go into new array</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token function">setTodos</span><span class="token punctuation">(</span>todosCopy<span class="token punctuation">)</span> <span class="token comment">//This works!</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>This is because React wants to encourage data to remain <strong>immutable</strong> (you don’t change it, you just make a altered copy) and for functions to avoid <strong>side effects</strong> (where they change something outside of themselves) in order to help maintain consistency of your data.</p>
<ul>
<li><p>The <code>.map()</code> function is usually the easiest way to copy an array, though other techniques exist as well. If you wish to copy an <em>object</em>, you can do this easily using the <em>spread operator</em> to create a new object using the properties of the first:</p>
<pre class="language-js"><code><span class="token comment">//an original object</span>
<span class="token keyword">const</span> original <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token literal-property property">a</span><span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token literal-property property">b</span><span class="token operator">:</span> <span class="token number">2</span><span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token comment">//Create a copy, taking the property of `original` and assigning them into</span>
<span class="token comment">//a fresh object</span>
<span class="token keyword">const</span> copy <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token operator">...</span>original <span class="token punctuation">}</span> <span class="token comment">//using the spread operator</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>copy<span class="token punctuation">)</span> <span class="token comment">//{a: 1, b: 2}</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>copy <span class="token operator">==</span> original<span class="token punctuation">)</span> <span class="token comment">//false, different objects</span></code></pre>
<p>(The <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign"><code>Object.assign()</code> function</a>) is also used to do a similar operation, but the spread operator is easier to read)</p></li>
</ul>
</div>
<div id="state-vs.-props" class="section level3 unnumbered">
<h3>State vs. Props</h3>
<p>Importantly, a Component’s <em>state</em> is different from its <em>props</em>. Although state and props make look similar, they have very different roles. Many developers get the two confused—to the point that React has an <a href="https://reactjs.org/docs/faq-state.html#what-is-the-difference-between-state-and-props">FAQ</a> entry about the difference!</p>
<p>The key difference between props and state is:</p>
<blockquote>
<p><code>props</code> are for information that doesn’t change from the Component’s perspective, including “initial” data. <code>state</code> is for information that will change, usually due to user interaction.</p>
</blockquote>
<p>Props are the “inputs” into a component, the values that someone else tells the Component it should. That is why the are passed in as arguments! <em>Props are immutable</em>—from the component’s perspective; they cannot be changed once set (though a parent could create a <em>different</em> version of the component with different props).</p>
<p>State is “internal” to the Component, and is (only) for values that change over time. If the value doesn’t change over the life of the Component (e.g., in response to a user event), it shouldn’t be part of the state! To quote from <a href="https://reactjs.org/docs/thinking-in-react.html">the documentation</a>:</p>
<blockquote>
<p>State is reserved only for interactivity, that is, data that changes over time.</p>
</blockquote>
<p>For example, a <code>SortableTable</code> component might be used to render a list of data. But as the data in the list would come from elsewhere (e.g., the overall <code>App</code>) and wouldn’t be changed <em>by the table</em>, it would be passed in as a <code>prop</code>. However, the <em>order</em> in which that data is displayed might change—thus you could save an <code>orderBy</code> value in the state, and then use that to organize what elements are returned by the component function. The data itself doesn’t change, but how it is rendered does!</p>
<!-- Add example? Can do sorting by column-name easily? :/ -->
<p>It is possible to use the props to initialize a state variable (since props are the “initial values” for the Component), though the props would not be changed later:</p>
<pre class="language-jsx"><code><span class="token comment">//A component representing a count</span>
<span class="token keyword">function</span> <span class="token function">Counter</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 keyword">const</span> <span class="token punctuation">[</span>count<span class="token punctuation">,</span> setCount<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">useState</span><span class="token punctuation">(</span>props<span class="token punctuation">.</span>startAt<span class="token punctuation">)</span>
<span class="token punctuation">}</span>
<span class="token keyword">let</span> counter <span class="token operator">=</span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span><span class="token class-name">Counter</span></span> <span class="token attr-name">startAt</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span><span class="token number">5</span><span class="token punctuation">}</span></span> <span class="token punctuation">/></span></span></code></pre>
<p>In this case the state variable keeps track of the count, though the prop specifies an initial number. The <code>count</code> variable will change in the future, but the <code>props.startAt</code> value will not.</p>
<p>It’s important that you <em>only</em> use state to track values that will change over the life of the Component. If you’re not sure if a value should be part of the state, consider the following:</p>
<ol style="list-style-type: decimal">
<li>Is the value passed in from a parent via props? If so, it probably isn’t state.</li>
<li>Does the value remain unchanged over time? If so, it definitely isn’t state.</li>
<li>Can you compute it based on any other state or props in your component? If so, it definitely isn’t state.</li>
</ol>
<p>The last of these rules is important. In general, you should keep the state as <em>minimal as possible</em>—meaning you want to have as little data as possible in the state. This is to help avoid duplicating information (which can get out of sync), as well as to speed up how React will “re-render” Components when the state changes.</p>
<p class="alert alert alert-warning">
One of the most difficult parts of architecting a React application is figuring out what information should be stored in the props or state (and in which components). We suggest you practice using simple examples, and think carefully about it as you build more robust applications.
</p>
</div>
<div id="lifting-up-state" class="section level3 unnumbered">
<h3>Lifting Up State</h3>
<p>In React, a component state is purely <em>internal</em> to that component—neither the component’s parent element nor its children have access to (or are even aware of) that state. State represents only information about that particular component (and that particular <em>instance</em> of the component).</p>
<p>Sometimes a child component (i.e., a component instantiated as part of the returned DOM) needs some data that is stored in the state—for example, a <code>BlogPost</code> component might need a data value that is stored in the <code>Blog</code>’s <code>comments</code> state variable. Components can make information available to their children by passing that data to them as a <em>prop</em>:</p>
<pre class="language-jsx"><code><span class="token keyword">function</span> <span class="token function">Blog</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 keyword">const</span> <span class="token punctuation">[</span>posts<span class="token punctuation">,</span> setPosts<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">useState</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token operator">...</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token comment">//initialize the state</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>h2</span><span class="token punctuation">></span></span>Most Recent Post<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>h2</span><span class="token punctuation">></span></span>
<span class="token punctuation">{</span><span class="token comment">/* pass in values from state as a prop */</span><span class="token punctuation">}</span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span><span class="token class-name">BlogPost</span></span> <span class="token attr-name">postText</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span>posts<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><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></code></pre>
<p>In this example, the <code>BlogPost</code> would be passed the individual “post text” data as a normal prop, without being aware that the data was actually stored in the <code>Blog</code>’s state. When that data changes (e.g., when a new post is added), the component function will be called again and the <code>BlogPost</code> component will be re-instantiated with a new value for its prop—again, without any knowledge that there was a change. From the perspective of the <code>BlogPost</code>, there has only ever been a single <code>postText</code> value (the <code>BlogPost</code> with a different text is actually a different <code>BlogPost</code> object!).</p>
<p>While passing state data to a child (as a prop) is easy, communicating state data to a <em>parent</em> or <em>sibling</em> is more complicated. For example, you may want to have a <code>SearchForm</code> component that is able to search for data, but want to then have a sibling <code>ResultsList</code> component that is able to display the rendered results:</p>
<pre class="language-jsx"><code><span class="token tag"><span class="token tag"><span class="token punctuation"><</span><span class="token class-name">App</span></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">SearchForm</span></span> <span class="token punctuation">/></span></span> <span class="token punctuation">{</span><span class="token comment">/* has the data */</span><span class="token punctuation">}</span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span><span class="token class-name">ResultsList</span></span> <span class="token punctuation">/></span></span> <span class="token punctuation">{</span><span class="token comment">/* needs the data */</span><span class="token punctuation">}</span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span><span class="token class-name">App</span></span><span class="token punctuation">></span></span></code></pre>
<p>When confronted with this problem, the best practice in React is to <strong>lift the state up</strong> to the the <em>closest common ancestor</em>. This means that instead of having the data be stored in the state of one of the children, you instead store the data in the state of the <em>parent</em>. The parent can then pass that information down to the children (as props) for them to use. This way the data always flows “down” the tree.</p>
<div class="figure">
<img src="img/react/lift-up.gif" alt="" />
<p class="caption">“Lift up” the state to the closest common ancestor to share data between sibling elements</p>
</div>
<p>But with the state stored in the parent, the children elements (e.g., the <code>SearchForm</code>) may still need a way to interact with that parent and tell it to change its state. To do this, you can have the parent define a function that changes its state, and then pass the child that <em>callback function</em> as a <code>prop</code>. The child will then be able to execute that callback prop, thereby telling the parent to do something (such as update its state!)</p>
<ul>
<li>It’s like the parents write down their instructions, and then hand them to the child to do later!</li>
</ul>
<p>In the following example, the parent component (<code>VotingApp</code>) stores state data about how many times each button has been pressed, passing a callback function (<code>countClick</code>) to its child Components (<code>CandidateButton</code>). The <code>CandidateButton</code> will then execute that callback when it is clicked. Executing this function causes the <code>VotingApp</code> to update its state and re-render the buttons, which show updated text based on the props given to them (namely: who is winning!).</p>
<pre class="language-jsx"><code><span class="token keyword">function</span> <span class="token function">VotingApp</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">//initialize the state counts, one for each color</span>
<span class="token comment">//using a single state value so that there is only one "update" function</span>
<span class="token keyword">const</span> <span class="token punctuation">[</span>counts<span class="token punctuation">,</span> setCounts<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">useState</span><span class="token punctuation">(</span><span class="token punctuation">{</span><span class="token literal-property property">red</span><span class="token operator">:</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token literal-property property">blue</span><span class="token operator">:</span> <span class="token number">0</span><span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token comment">//a function to update the state</span>
<span class="token comment">//expects a "color" for which button was clicked</span>
<span class="token keyword">const</span> <span class="token function-variable function">handleCount</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">color</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>color <span class="token operator">+</span> <span class="token string">" got a vote!"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> newCounts <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token operator">...</span>counts <span class="token punctuation">}</span> <span class="token comment">//make a duplicate of the object</span>
newCounts<span class="token punctuation">[</span>color<span class="token punctuation">]</span><span class="token operator">++</span><span class="token punctuation">;</span> <span class="token comment">//update the local copy</span>
<span class="token function">setCounts</span><span class="token punctuation">(</span>newCounts<span class="token punctuation">)</span> <span class="token comment">//update the state with the changed copy</span>
<span class="token punctuation">}</span>
<span class="token comment">//render based on current state</span>
<span class="token keyword">let</span> winner <span class="token operator">=</span> <span class="token string">"tie"</span><span class="token punctuation">;</span>
<span class="token keyword">if</span><span class="token punctuation">(</span>counts<span class="token punctuation">.</span>red <span class="token operator">></span> counts<span class="token punctuation">.</span>blue<span class="token punctuation">)</span> winner <span class="token operator">=</span> <span class="token string">"red"</span>
<span class="token keyword">else</span> <span class="token keyword">if</span><span class="token punctuation">(</span>counts<span class="token punctuation">.</span>blue <span class="token operator">></span> counts<span class="token punctuation">.</span>red<span class="token punctuation">)</span> winner <span class="token operator">=</span> <span class="token string">"blue"</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>p</span><span class="token punctuation">></span></span>Current winner is<span class="token operator">:</span> <span class="token punctuation">{</span>winner<span class="token punctuation">}</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 punctuation">{</span><span class="token comment">/* Pass the callback to each button as a prop */</span><span class="token punctuation">}</span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span><span class="token class-name">CandidateButton</span></span> <span class="token attr-name">color</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>red<span class="token punctuation">"</span></span> <span class="token attr-name">winner</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span>winner<span class="token punctuation">}</span></span> <span class="token attr-name">callback</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span>handleCount<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><span class="token class-name">CandidateButton</span></span> <span class="token attr-name">color</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>blue<span class="token punctuation">"</span></span> <span class="token attr-name">winner</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span>winner<span class="token punctuation">}</span></span> <span class="token attr-name">callback</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span>handleCount<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>
<span class="token keyword">function</span> <span class="token function">CandidateButton</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 keyword">const</span> <span class="token function-variable function">handleClick</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 comment">//On click, execute the given callback function (passing in own name)</span>
props<span class="token punctuation">.</span><span class="token function">callback</span><span class="token punctuation">(</span>props<span class="token punctuation">.</span>color<span class="token punctuation">)</span>
<span class="token punctuation">}</span>
<span class="token comment">//render based on current props</span>
<span class="token keyword">let</span> label <span class="token operator">=</span> <span class="token string">"I am not winning"</span><span class="token punctuation">;</span>
<span class="token keyword">if</span><span class="token punctuation">(</span>props<span class="token punctuation">.</span>winner <span class="token operator">===</span> props<span class="token punctuation">.</span>color<span class="token punctuation">)</span>
label <span class="token operator">=</span> <span class="token string">"I am winning!"</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>button</span> <span class="token attr-name">className</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span>props<span class="token punctuation">.</span>color<span class="token punctuation">}</span></span> <span class="token attr-name">onClick</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span>handleClick<span class="token punctuation">}</span></span><span class="token punctuation">></span></span>
<span class="token punctuation">{</span>label<span class="token punctuation">}</span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>button</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>As with many React systems, there are a lot of moving parts that fit together. To understand how this example works, try “tracing” the code that occurs when the <code>CountingApp</code> is first rendered, and then what happens when a button is clicked. Remember that calling <code>setCounts()</code> causes the component to be re-rendered (the function is re-run)!</p>
<p>Finally, notice in particular that the <code>CandidateButton</code> class knows nothing about its parent or indeed any information about how it is used (or even if there are other <code>CandidateButton</code> instances). Instead, it simply renders itself based on its props, and executes whatever <code>callback</code> function it was given whenever it is clicked (without carrying about what that function does). Having lots of “simple” components like this is the best way to design React apps.</p>
<p>In summary, in order to make an interactive React application, perform the following steps:</p>
<ol style="list-style-type: decimal">
<li>Start with a “static” (non-interactive) version, with appropriate Components</li>
<li>Identify variables that will change so need to be stored in the state</li>
<li>Define state variables in the “lowest” common ancestor for Components that need it</li>
<li>Pass state information to child Components as <code>props</code></li>
<li>Pass <em>callback functions</em> as <code>props</code> to child Components so they can modify the state.</li>
</ol>
</div>
</div>
<div id="specific-interactions" class="section level2" number="16.3">
<h2><span class="header-section-number">16.3</span> Specific Interactions</h2>
<p>This section provides some details on specific types of interactions commonly used in React apps but require further details and explanation.</p>
<div id="working-with-forms" class="section level3 unnumbered">
<h3>Working with Forms</h3>
<p>One of the most common reasons to track state in a React app is when developing <a href="https://reactjs.org/docs/forms.html">forms</a> that the user can fill out to submit information. Forms are a common structure to use when getting user input—whether it’s a “search form” for browsing a data set, or a “login form” for allowing a user access to personalized data.</p>
<p>In normal HTML, form elements such as <strong><code><input></code></strong> keep track of their own “state”. For example, whatever the user has typed into a text input will be stored in that input’s <code>value</code> property:</p>
<pre class="language-js"><code><span class="token comment">//Select the <input type="text"> element</span>
<span class="token keyword">let</span> textInput <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">querySelector</span><span class="token punctuation">(</span><span class="token string">'input[type="text"]'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">//Event that occurs whenever the input is changed</span>
textInput<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'change'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">event</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">let</span> input <span class="token operator">=</span> event<span class="token punctuation">.</span>target<span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>input<span class="token punctuation">.</span>value<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//access that elements "state"</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>You will often want React to be able to respond to user data entered into a form—either because you want to send an AJAX request based on that data, or because you want to perform <strong>form validation</strong> and confirm that the user has entered appropriate input (e.g., that the password is at least 6 characters long). But storing the user input in the <code><input></code> element’s state can cause problem for React: React components won’t know that they should “rerender” when that changes, and updating a React component might cause the entire DOM tree to re-render (producing a new <code><input></code> element with a different <code>value</code> state).</p>
<p>Thus the recommended practice for working with forms in React is to use <a href="https://reactjs.org/docs/forms.html#controlled-components"><strong>controlled Components</strong></a>. In this case, you define a component that will track the state of what the user has typed into the <code><input></code>, and then will render an <code><input></code> with an appropriate <code>value</code> property. Rather than letting the <code><input></code> control its own state, the React component controls the state and then dictates to the <code><input></code> element what value it should be showing. It’s like React is snatching the data from the <code><input></code> and then claiming credit for it.</p>
<pre class="language-jsx"><code><span class="token keyword">function</span> <span class="token function">MyInput</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 keyword">const</span> <span class="token punctuation">[</span>inputValue<span class="token punctuation">,</span> setInputValue<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">useState</span><span class="token punctuation">(</span><span class="token string">''</span><span class="token punctuation">)</span><span class="token comment">//initialize as empty string</span>
<span class="token comment">//respond to input changes</span>
<span class="token keyword">const</span> <span class="token function-variable function">handleChange</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">event</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token comment">//get the value that the <input> now has</span>
<span class="token keyword">let</span> newValue <span class="token operator">=</span> event<span class="token punctuation">.</span>target<span class="token punctuation">.</span>value
<span class="token comment">//update the state to use that new value, rendering the component</span>
<span class="token function">setInputValue</span><span class="token punctuation">(</span>newValue<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</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 punctuation">{</span><span class="token comment">/* The input will be rendered with the React-controlled value */</span><span class="token punctuation">}</span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>input</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>text<span class="token punctuation">"</span></span> <span class="token attr-name">onChange</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span>handleChange<span class="token punctuation">}</span></span> <span class="token attr-name">value</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span>inputValue<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>p</span><span class="token punctuation">></span></span>You typed<span class="token operator">:</span> <span class="token punctuation">{</span>inputValue<span class="token punctuation">}</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>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>The above is an example of a basic controlled Component. When the user enters a different value into the <code><input></code> element, the <code>handleChange()</code> callback is executed. This grabs that updated value and saves it in the component’s <code>inputValue</code> state variable. Updating that state variable also causes the component to re-render, which recreates a brand new version of the <code><input></code> element, but now with the React-controlled value for its <code>value</code> attribute. This way whatever value the user has entered will always be part of a React Component’s state, and so can be manipulated and interacted with in the same manner.</p>
<ul>
<li><p>And of course, a controlled form might render multiple <code><input></code> elements, tracking the values of each one in a separate variable in the state. This also allows the inputs to easily interact with each other, such if you want to confirm that a password was entered correctly twice.</p></li>
<li><p>Robust form validation is actually quite tricky in React (especially when compared to other frameworks such as Angular). Using an external library such as <a href="https://jaredpalmer.com/formik">Formik</a> can help with developing forms and handling all the edge cases.</p></li>
</ul>
</div>
<div id="fetching-data-via-ajax" class="section level3 unnumbered">
<h3>Fetching Data via AJAX</h3>
<p>One of the most common use of lifecycle callback functions is when accessing data asynchronously, such as when fetching data via an AJAX request (such a described in <a href="ajax.html#ajax">Chapter 14</a>). This section provides details about how to asynchronously load data within the React framework.</p>
<p>First, remember that React code is <em>transpiled</em> using Webpack. As such, some APIs—including <code>fetch()</code> are not “built-in” to React like they are with a modern browser. As discussed in <a href="ajax.html#fetching-data">Chapter 14</a>, in order to support these “other” browsers, you will need to load a <em>polyfill</em>. You can do that with React by installing the <code>whatwg-fetch</code> library, and then <code>import</code>ing that polyfill in your React code:</p>
<pre class="language-bash"><code><span class="token comment"># On command line, install the polyfill</span>
<span class="token function">npm</span> <span class="token function">install</span> whatwg-fetch</code></pre>
<pre class="language-js"><code><span class="token comment">//In your JavaScript, import the polyfill (loading it "globally")</span>
<span class="token comment">//This will make the `fetch()` function available</span>
<span class="token keyword">import</span> <span class="token string">'whatwg-fetch'</span><span class="token punctuation">;</span></code></pre>
<p>Remember that <code>fetch()</code> downloads data <em>asynchronously</em>. Thus if you want to download some data to display, it may take a while to arrive. You don’t want React to have to “wait” for the data (since React is designed to be <em>fast</em>). Thus the best practice is to send the <code>fetch()</code> request for data, and <code>then</code> when the data has been downloaded, call the a set state function to update the component with the downloaded data. (The component can initialize its state as an “empty array” of data).</p>
<p>Fetching data from the internet is considered a <a href="https://en.wikipedia.org/wiki/Side_effect_(computer_science)"><strong>side effect</strong></a> in React. Function components are supposed to do one thing (as well-designed “pure” functions): they return the DOM that will be rendered on the screen. But downloading data modifies something outside of that framework, in that it modifies network status/information and even the status of the remote server! Thus calling <code>fetch()</code> from directly inside the component function would be considered bad programming style, and can cause problems and bugs when the component is rendered. For example, if the fetched data returns too quickly or too slowly, you may try and set the state variable of (and thus rerender) a component that isn’t yet attached to the DOM, causing React to crash. And if the state does update and reruns the component, that would cause it to download the data yet again, potentially causing an infinite loop!</p>
<p>In order to perform side effect operations in React, you need to use another kind of hook called an <a href="https://reactjs.org/docs/hooks-effect.html"><strong>effect hook</strong></a>, provided by the React function <strong><code>useEffect()</code></strong>. An effect hook lets you hook into the lifecycle of a component, specifying some code (a function) that should be run <em>after</em> the component finishes rendering. Any code that will produce a side effect (such as downloading data, manipulating the DOM outside of React rendering, or setting up subscriptions to a data source) should be run through an effect hook. That’s why they’re called <em>effect</em> hooks: because they define a side effect to the component rendering.</p>
<p>An example of using the event hook to download data is below, followed by an explanation of the syntax.</p>
<pre class="language-jsx"><code><span class="token comment">//import the hooks used</span>
<span class="token keyword">import</span> React<span class="token punctuation">,</span> <span class="token punctuation">{</span> useState<span class="token punctuation">,</span> useEffect <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'react'</span><span class="token punctuation">;</span>
<span class="token keyword">function</span> <span class="token function">MyComponent</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">//store the data in a state variable, initialized as an empty array</span>
<span class="token keyword">const</span> <span class="token punctuation">[</span>data<span class="token punctuation">,</span> setData<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">useState</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 comment">//specify the effect hook function</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 function">fetch</span><span class="token punctuation">(</span>dataUri<span class="token punctuation">)</span> <span class="token comment">//send AJAX request</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 parameter">res</span><span class="token punctuation">)</span> <span class="token operator">=></span> res<span class="token punctuation">.</span><span class="token function">json</span><span class="token punctuation">(</span><span class="token punctuation">)</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 parameter">data</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">let</span> processedData <span class="token operator">=</span> data<span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span><span class="token operator">...</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token operator">...</span><span class="token punctuation">)</span> <span class="token comment">//do desired processing</span>
<span class="token function">setData</span><span class="token punctuation">(</span>processedData<span class="token punctuation">)</span> <span class="token comment">//change the state and re-render</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><span class="token punctuation">)</span> <span class="token comment">//empty array is the second argument to the `useEffect()` function.</span>
<span class="token comment">//It says to only run this effect on first render</span>
<span class="token comment">//Map the data values into DOM elements</span>
<span class="token comment">//Note that this works even before data is loaded (when the array is empty!)</span>
<span class="token keyword">let</span> dataItems <span class="token operator">=</span> data<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">item</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 tag"><span class="token tag"><span class="token punctuation"><</span>li</span> <span class="token attr-name">key</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span>item<span class="token punctuation">.</span>id<span class="token punctuation">}</span></span><span class="token punctuation">></span></span><span class="token punctuation">{</span>item<span class="token punctuation">.</span>value<span class="token punctuation">}</span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>li</span><span class="token punctuation">></span></span><span class="token punctuation">;</span> <span class="token comment">//return DOM version of datum</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token comment">//render the data items (e.g., as a list)</span>
<span class="token keyword">return</span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>ul</span><span class="token punctuation">></span></span><span class="token punctuation">{</span>dataItems<span class="token punctuation">}</span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>ul</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>Calling the <code>useEffect()</code> function specifies a callback function that will be run <em>after</em> the component renders. Things to notice about how this function is used:</p>
<ul>
<li><p>As with the state hook, the effect hook function <code>useEffect</code> must be imported (as a named import).</p></li>
<li><p>The <code>useEffect()</code> function takes as an argument the callback function to run after the component renders. This is usually specified as an arrow function, though you could of course give it a named function. Note that the callback takes no arguments.</p></li>
<li><p>Inside the <code>useEffect()</code> callback goes the normal <code>fetch()</code> call. Notice that the downloaded data is then assigned to the component’s state variable by calling the set state function (named <code>setData()</code> in this example).</p>
<p>While technically it means the component is rendering twice (once without data, then once with), React can batch these requests together so that if the data downloads fast enough, the user will not notice. This is also a good reason to <a href="https://reactjs.org/docs/conditional-rendering.html">conditionally</a> include DOM elements like spinners when rendering data.</p></li>
<li><p>By default, the effect callback will be executed after <em>each</em> time the component renders. That means that if the component needed to re-render (because a prop changed for example), then the data would be downloaded a second time! To avoid this, you can pass the <code>useEffect()</code> function an optional second argument. This argument should be an array of values that the effect “depends on”—the effect will only be re-run if one of these variables changes between renders:</p>
<pre class="language-js"><code><span class="token comment">//an effect that only re-runs if the `count` variable changes</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 comment">//...</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">[</span>count<span class="token punctuation">]</span><span class="token punctuation">)</span></code></pre>
<p>By passing an empty array as a second argument, you tell the effect that it should only re-run if one of those (non-existent) variables updates—and since there are no variables listed, it will never run a second time!</p></li>
<li><p>The <code>useEffect()</code> function does not need to return any values. In fact, the only value it can return is a “cleanup” callback function, which React will run whenever the component is removed from the DOM:</p>
<pre class="language-js"><code><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 comment">//...</span>
<span class="token keyword">return</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 comment">//function name is arbitrary</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"component has been removed!"</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span></code></pre>
<p>This is only necessary for side effects that require cleanup, such as subscribing to a data source or handling some user authentication behaviors. It is not needed for basic <code>fetch()</code> calls.</p></li>
</ul>
<p class="alert alert-info">
There are a number of other hooks available in React as well. Check the <a href="https://reactjs.org/docs/hooks-reference.html">documentation</a> for details. Note that in general, you should only look into a hook if you’re hitting an architectural problem (e.g., you have a lot of repeated code)—otherwise stick with the basic structure of props and state!
</p>
<!-- External libraries (e.g., react-strap) should go somewhere... maybe a third React chapter? -->
</div>
</div>
<div id="resources-13" class="section level2 unnumbered">
<h2>Resources</h2>
<div class="list-condensed">
<ul>
<li><a href="https://reactjs.org/docs/handling-events.html">Handling Events</a></li>
<li><a href="https://reactjs.org/docs/hooks-state.html">Using the State Hook</a></li>
<li><a href="https://github.com/uberVU/react-guide/blob/master/props-vs-state.md">props vs state (blog)</a></li>
<li><a href="https://reactjs.org/docs/faq-state.html">FAQ: Component State</a></li>
<li><a href="https://reactjs.org/docs/lifting-state-up.html">Lifting State Up</a></li>
<li><a href="https://reactjs.org/docs/forms.html">React Forms</a></li>
<li><a href="https://wattenberger.com/blog/react-hooks">Thinking in React Hooks</a></li>
</ul>
</div>
</div>
</div>
</section>
</div>
</div>
</div>
<a href="react.html" class="navigation navigation-prev " aria-label="Previous page"><i class="fa fa-angle-left"></i></a>
<a href="client-side-routing.html" class="navigation navigation-next " aria-label="Next page"><i class="fa fa-angle-right"></i></a>
</div>
</div>
<script src="libs/gitbook-2.6.7/js/app.min.js"></script>
<script src="libs/gitbook-2.6.7/js/clipboard.min.js"></script>
<script src="libs/gitbook-2.6.7/js/plugin-search.js"></script>
<script src="libs/gitbook-2.6.7/js/plugin-sharing.js"></script>
<script src="libs/gitbook-2.6.7/js/plugin-fontsettings.js"></script>
<script src="libs/gitbook-2.6.7/js/plugin-bookdown.js"></script>
<script src="libs/gitbook-2.6.7/js/jquery.highlight.js"></script>
<script src="libs/gitbook-2.6.7/js/plugin-clipboard.js"></script>
<script>
gitbook.require(["gitbook"], function(gitbook) {
gitbook.start({
"sharing": {
"github": true,
"facebook": false,
"twitter": false,
"linkedin": false,
"weibo": false,
"instapaper": false,
"vk": false,
"whatsapp": false,
"all": ["github", "facebook", "twitter", "google"],
"google": false
},
"fontsettings": {
"theme": "white",
"family": "sans",
"size": 2
},
"edit": {
"link": "https://github.com/info340/book/edit/master/react-interactive.Rmd",