-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathclient-side-routing.html
More file actions
938 lines (883 loc) · 117 KB
/
client-side-routing.html
File metadata and controls
938 lines (883 loc) · 117 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
<!DOCTYPE html>
<html lang="en" xml:lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>Chapter 17 Client-Side Routing | 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 17 Client-Side Routing | 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 17 Client-Side Routing | 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="interactive-react.html"/>
<link rel="next" href="ajax.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="client-side-routing" class="section level1" number="17">
<h1><span class="header-section-number">Chapter 17</span> Client-Side Routing</h1>
<p>This chapter discusses how to use React to effectively develop <strong>Single Page Applications (SPA)</strong>—web applications that are located on a single web page (HTML file), but DOM manipulation (and often AJAX requests) to produce the <em>appearance</em> of multiple “web pages”. This structure is facilitated by the use of the <em>client-side routing</em> library <code>react-router</code>, which allows you to render different Components based on the browser’s URL, allowing each View (“page”) to be treated as a unique <a href="https://en.wikipedia.org/wiki/Web_resource">resource</a>.</p>
<div id="single-page-applications" class="section level2" number="17.1">
<h2><span class="header-section-number">17.1</span> Single-Page Applications</h2>
<p>As you’ve seen in previous chapters, the React framework lets you dynamically render different <em>Views</em> (Components) based on different conditions such as the <code>state</code> of the app. For example, you can have a blogging app that could have a <code>blogPostId</code> state variable, and then use that variable to determine which blog post to display. Often these Views act as entirely separate <strong>pages</strong>—you either show one View or an another. As such, you’d often like each View to be treated as an individual <em>resource</em> and so to have its own <a href="https://en.wikipedia.org/wiki/Uniform_Resource_Identifier"><strong>URI</strong></a>, thus allowing each View to be referenced individually. For example, each blog post could have it’s own URI, allowing a user to type in a particular URL to see a specific post (and letting that user share the post with others).</p>
<!-- - While you could achieve unique URIs by making each View be a separate HTML file (e.g., `index.html`, `about.html`), this quickly becomes infeasible for a large amount of resources, such as when you want to make a new "web page" for each blog post stored in a database. Moveover, separate `.html` files would not be able to share data/state or components (e.g., a shared navigation element). -->
<p>In order to achieve this effect, you can use <strong>client-side routing</strong>. With client-side routing, determining which View to display based on the URL (how to “route”, or map that URL to the correct resource) is performed on the <em>client-side</em> by JavaScript code. This is distinct from <em>server-side routing</em>, in that the server isn’t deciding which resource to show (i.e., which <code>.html</code> file to respond to a request with), but rather responds with a single HTML file whose JavaScript dynamically determines what resource to show (i.e., which React component to render) based on the <em>URI</em> that request was sent to!</p>
<ul>
<li>In this context, “routing” involves taking the resource identifier (the URI) and determining what <em>representation</em> of that resource should be displayed—what View to show. A “route” is thus a URI, which will refer to a particular View of the resource.</li>
</ul>
<p>Client-side routing allows you to have unique URLs for each View, but will also make the app work faster—instead of needing to download an entire brand new page from the server, you only need to download the requisite extra data (e.g., using an AJAX request), with much of the other content (the HTML, CSS, etc) already being in place. Moreover, this will all your app to easily share both state data and particular components (e.g., headers, navigation, etc).</p>
<ul>
<li><a href="https://drive.google.com">Google Drive</a> is a good example of a Single-Page Application. Notice how if you navigate to a new folder, the URL changes (so you can link to individual folders), but only a single “pane” of the page changes.</li>
</ul>
<p>Because React applications are component-based, you can perform <em>client-side routing</em> in React by using <a href="https://reactjs.org/docs/conditional-rendering.html">conditional rendering</a> to only render components if the current route is correct. This follows a structure similar to:</p>
<pre class="language-jsx"><code><span class="token keyword">function</span> <span class="token function">App</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">//pick a component based on the URL</span>
<span class="token keyword">let</span> componentToRender <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
<span class="token keyword">if</span><span class="token punctuation">(</span>currentUrl <span class="token operator">===</span> <span class="token string">'/home'</span><span class="token punctuation">)</span><span class="token punctuation">{</span> <span class="token comment">//pseudocode comparison with URL</span>
componentToRender <span class="token operator">=</span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span><span class="token class-name">HomePage</span></span> <span class="token punctuation">/></span></span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">else</span> <span class="token keyword">if</span><span class="token punctuation">(</span>currentUrl <span class="token operator">===</span> <span class="token string">'/about'</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
componentToRender <span class="token operator">=</span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span><span class="token class-name">AboutPage</span></span> <span class="token punctuation">/></span></span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">//render that component</span>
<span class="token keyword">return</span> componentToRender<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>That is, <em>if</em> the current URL <strong>matches</strong> a particular route, then the Component will be rendered.</p>
</div>
<div id="react-router" class="section level2" number="17.2">
<h2><span class="header-section-number">17.2</span> React-Router</h2>
<p>Third-party libraries such as <a href="https://reactrouter.com/en/6.4.4"><strong>React Router</strong></a> provide Components that include this “matching” functionality, allowing you to easily develop single-page applications.</p>
<p class="alert alert-warning">
This chapter details how to use <a href="https://reactrouter.com/7.1.5/home"><strong>version 7</strong></a> of React Router, released in <em>November 2021</em>. This version is significantly different from the previous versions (particularly v5). Be careful when looking up examples and resources that they’re utilizing the same version as you! For details about earlier versions of the React Router, see <a href="https://v5.reactrouter.com/">the documentation for those versions</a>. Importantly, this chapter teaches how to use React Router as a <strong>library</strong>, not as a Framework.
</p>
<p>As with other libraries, you <a href="https://reactrouter.com/7.1.5/start/library/installation">begin using React Router</a> by installing the <code>react-router</code> library:</p>
<pre class="language-bash"><code><span class="token function">npm</span> <span class="token function">install</span> react-router</code></pre>
<p>You will then need to <code>import</code> any Components you wish to use into the <code>.js</code> files containing your React code. For example:</p>
<pre class="language-js"><code><span class="token comment">//import BrowserRouter, Routes, Route, and Link from react-router</span>
<span class="token keyword">import</span> <span class="token punctuation">{</span> BrowserRouter<span class="token punctuation">,</span> Routes<span class="token punctuation">,</span> Route<span class="token punctuation">,</span> Link<span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'react-router'</span></code></pre>
<p>These Components are described in the following sections.</p>
<div id="routing" class="section level3 unnumbered">
<h3>Routing</h3>
<p>The <strong><code><BrowserRouter></code></strong> Component (which is often imported with an alias of <code><Router></code>—though there is also a <code><Router></code> component!) is the “base” Component used by React Router. This Component does all the work of keeping the React app’s UI (e.g., which Components are rendered) in sync with the browser’s URL. The <code>BrowserRouter</code> “listens” for changes to the URL, and then passes information about the current route (called the <strong><code>path</code></strong>) to its child components. This allows each child to always know what route is currently shown in the URL, without needing to access the URL directly.</p>
<ul>
<li><p>With React Router, a “route” is defined by the <em>path</em> portion of a URI (see <a href="#http-requests-and-servers">Chapter 2</a>). This is the part that comes <em>after</em> the protocol and domain (e.g., after the <code>https://mydomain.com/</code>). Thus the <code>/home</code> route would refer to the URI <code>https://mydomain.com/home</code>, while the <code>/about</code> route would refer to the URI <code>https://mydomain.com/about</code>.</p></li>
<li><p><code>BrowserRouter</code> utilizes the <a href="https://developer.mozilla.org/en-US/docs/Web/API/History_API">HTML5 history API</a> to interact with the brower’s URL and history (what allows you to go “back” and “forward” between URLs). This API is supported by <a href="https://caniuse.com/#feat=history">modern browsers</a>, but older browsers (i.e., IE 9) would need to use <code><HashRouter></code> as an drop-in alternate. <code>HashRouter</code> uses the <a href="https://en.wikipedia.org/wiki/Fragment_identifier">fragment identifier</a> portion of the URI to track what “page” the app should be showing, causing URL’s to include an extra hash <code>#</code> symbol in them (e.g., <code>https://mydomain.com/#/about</code>).</p></li>
<li><p>Your app will only ever have a single <code><BrowserRouter></code> component in it–usually at the “top level” of your application (so it would contain <code><App></code> as a child). Thus the <code><BrowserRouter></code> is usually rendered in the <code>index.html</code> file:</p>
<pre class="language-jsx"><code><span class="token comment">//index.js</span>
<span class="token keyword">import</span> <span class="token punctuation">{</span> BrowserRouter <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'react-router'</span>
<span class="token keyword">import</span> App <span class="token keyword">from</span> <span class="token string">'./components/App.js'</span>
<span class="token comment">//render the App *inside* of the BrowserRouter</span>
<span class="token keyword">const</span> root <span class="token operator">=</span> ReactDOM<span class="token punctuation">.</span><span class="token function">createRoot</span><span class="token punctuation">(</span>document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'root'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
root<span class="token punctuation">.</span><span class="token function">render</span><span class="token punctuation">(</span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span><span class="token class-name">BrowserRouter</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">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">BrowserRouter</span></span><span class="token punctuation">></span></span>
<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></li>
</ul>
<p>Inside the <code><BrowserRouter></code> (usually inside of the <code><App></code>), you will define the <strong>routes</strong> for your application—the collection of supported paths and which View to show at each. You can specify route-based views using the <strong><code><Route></code></strong> Component. This component will render its <strong><code>element</code></strong> only when the current URL <em>matches</em> a specified <strong><code>path</code></strong>. In effect, the <code>Route</code> Component handles checking <em><code>if</code></em> the current URL matches the specified path, and if so renders its element. If the URL doesn’t match the route, then the element is not rendered. Both the <code>path</code> and the <code>element</code> are passed into the <code><Route></code> as props:</p>
<pre class="language-jsx"><code><span class="token keyword">function</span> <span class="token function">App</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">return</span> <span class="token punctuation">(</span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span><span class="token class-name">Routes</span></span><span class="token punctuation">></span></span> <span class="token punctuation">{</span><span class="token comment">/* the collection of routes to match */</span><span class="token punctuation">}</span>
<span class="token punctuation">{</span><span class="token comment">/* if currentUrlPath === "home" */</span><span class="token punctuation">}</span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span><span class="token class-name">Route</span></span> <span class="token attr-name">path</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>home<span class="token punctuation">"</span></span> <span class="token attr-name">element</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span><span class="token class-name">HomePage</span></span> <span class="token punctuation">/></span></span><span class="token punctuation">}</span></span> <span class="token punctuation">/></span></span>
<span class="token punctuation">{</span><span class="token comment">/* if currentUrlPath === "about" */</span><span class="token punctuation">}</span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span><span class="token class-name">Route</span></span> <span class="token attr-name">path</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>about<span class="token punctuation">"</span></span> <span class="token attr-name">element</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span><span class="token class-name">AboutPage</span></span> <span class="token punctuation">/></span></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><span class="token class-name">Routes</span></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>Points to notice about this example:</p>
<ul>
<li><p>The <code>path</code> prop is used to indicate the route that you wish to match—in particular, matching to the <em>path</em> part of the URL (after the domain). You do not include <code>http</code> or <code>domain.com</code> in the path.</p>
<p>The “root” segment <code>"/"</code> is used to match to a URL without a path (e.g., what to show at <code>http://domain.com</code>). Using a wildcard <code>*</code> in the path will match to “anything”, and is good for rendering “Page Not Found” elements.</p>
<p>The path can include multiple segments (e.g., <code>assignments/react</code>); however multiple segments usually correspond to <a href="client-side-routing.html#nesting-routes"><em>nested routes</em></a>, described below.</p></li>
<li><p>The Component (View) to render is passed in as the <code>element</code> prop. You instantiate the component using <code><Component/></code> syntax, and then that is passed as the inline expression (inside the <code>{}</code>). Yes, it makes the syntax look awkward.</p>
<p>You can of course pass additional props to the rendered component as normal:</p>
<pre class="language-jsx"><code><span class="token tag"><span class="token tag"><span class="token punctuation"><</span><span class="token class-name">Route</span></span> <span class="token attr-name">path</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>profile<span class="token punctuation">"</span></span> <span class="token attr-name">element</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span><span class="token class-name">ProfilePage</span></span> <span class="token attr-name">user</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span>userData<span class="token punctuation">}</span></span> <span class="token punctuation">/></span></span><span class="token punctuation">}</span></span> <span class="token punctuation">/></span></span></code></pre>
<p>While it is possible to pass <em>nested</em> elements as the <code>element</code> property, that can quickly become a readability nightmare. Better practice is to define a single “wrapper” Component to be rendered at the Route.</p></li>
<li><p><em>All</em> <code><Route></code> elements are made children of a <em>single</em> element called <strong><code><Routes></code></strong> (note the <code>s</code> makes it plural!). The <code><Routes></code> element represents the “collection” of Routes that the Router needs choose between when deciding what Component to render (if any). You can think of it as acting like a <code>switch</code> statement.</p>
<p>In practice, you will have a single <code><Routes></code> element in your page, usually in a top-level component such as <code><App></code>.</p>
<p>Note that a <code><Routes></code> can <em>only</em> have <code><Route></code> elements as children, and a <code><Route></code> element can <em>only</em> be the child of a <code><Routes></code>. They go together, and nothing else (no other <code><div></code>, etc. elements) can come between them. Though see <a href="client-side-routing.html#nesting-routes"><em>Nesting Routes</em></a> before for details on integrating different DOM layouts with your routing.</p></li>
</ul>
<div id="nesting-routes" class="section level4 unnumbered">
<h4>Nesting Routes</h4>
<p>In the above example, the Route’s <code>path</code> prop corresponds to a single <strong>segment</strong> of the URI path. Many React apps will want to differentiate the rendered content based on <em>multiple segments</em>. For example: the <code>/user/profile</code> path might show a <code><UserProfile></code> component, while the <code>user/favorites</code> path might show a <code><FavoriteItems></code> component (with the list of items the user has marked). Yet both of these paths might also want to show content shared by all Views that are part <code>/user</code> paths (but different from other non-user-specific paths, such as the <code>/items</code> path).</p>
<p>React Router supports this behavior by <strong>nesting routes</strong>—having one <code><Route></code> element be the child of another. For example:</p>
<pre class="language-jsx"><code><span class="token comment">// An example of nested routes</span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span><span class="token class-name">Routes</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">Route</span></span> <span class="token attr-name">path</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>user<span class="token punctuation">"</span></span> <span class="token attr-name">element</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span><span class="token class-name">UserLayout</span></span> <span class="token punctuation">/></span></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><span class="token class-name">Route</span></span> <span class="token attr-name">path</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>profile<span class="token punctuation">"</span></span> <span class="token attr-name">element</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span><span class="token class-name">UserProfile</span></span> <span class="token punctuation">/></span></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><span class="token class-name">Route</span></span> <span class="token attr-name">path</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>favorites<span class="token punctuation">"</span></span> <span class="token attr-name">element</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span><span class="token class-name">FavoriteItems</span></span> <span class="token punctuation">/></span></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><span class="token class-name">Route</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">Route</span></span> <span class="token attr-name">path</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>items<span class="token punctuation">"</span></span> <span class="token attr-name">element</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span><span class="token class-name">ItemList</span></span> <span class="token punctuation">/></span></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><span class="token class-name">Routes</span></span><span class="token punctuation">></span></span></code></pre>
<p>When the <code><Routes></code> element goes to match a URL and determine which element to render, it will start with with the first <em>segment</em> of the path, rendering that element. For example, if the path starts with <code>/user</code>, then the Router will render the <code><UserLayout></code> element. But it will then continue checking further segments of the path: so if the path is <code>/user/profile</code>, then the Router will render the <code><UserLayout></code> (for the <code>/user</code> part), but then render the <code><UserProfile></code> (for the <code>/profile</code> part) <em>inside</em> of the <code><UserLayout></code> at an indicated location. Thus you could view the above Routes as defining the following paths:</p>
<ul>
<li><code>/user/profile</code> renders <code><UserLayout><UserProfile/></UserLayout></code></li>
<li><code>/user/favorites</code> renders <code><UserLayout><UserFavorites/></UserLayout></code></li>
<li><code>/user</code> renders <code><UserLayout></UserLayout></code> (no child)</li>
<li><code>/items</code> renders <code><ItemList /></code></li>
</ul>
<p>(You can think of each “nested child” step as a <code>/</code> in the path)</p>
<p>You specify <em>where</em> in the parent element the child element will render using an <strong><code><Outlet></code></strong> Component. This component will be replaced by the element of whichever child route matches the URL segment:</p>
<pre class="language-jsx"><code><span class="token keyword">function</span> <span class="token function">UserLayout</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 function">render</span> <span class="token punctuation">(</span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">className</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>user-layout<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>h1</span><span class="token punctuation">></span></span>User Page<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>h1</span><span class="token punctuation">></span></span>
<span class="token punctuation">{</span><span class="token comment">/* will be replaced with <UserProfile>, <UserFavorites>, or null */</span><span class="token punctuation">}</span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span><span class="token class-name">Outlet</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>Thus you can think of the <code><Outlet /></code> as the “place the child component will go”.</p>
<p>Nested routes are primarily used to create shared layouts, as in the example above. The <code><UserLayout></code> component can contain structure elements (like divs) that will be shared across routes that begin with the same segment, but not other routes.</p>
<div class="alert alert-warning">
<p>
Not all apps require nesting routes! If your entire app has a single layout, you don’t need to create a separate Component for that; you can just render it as part of your <code><App></code> and use the <code><Routes></code> to specify the dynamic content.
</p>
<p>
Similarly, remember that Routes are <strong>only</strong> for conditionally rendering a Component <em>based on the URI</em>. If you want to conditionally show content (e.g., depending on whether the user is logged in, or based on what item has been selected), you use <a href="https://react.dev/learn/conditional-rendering">conditional rendering</a> based on the state—don’t use a Route!
</p>
</div>
<p>If you wish to show a “default” child Component when there is no further segment, you can give the child Route the <strong><code>index</code></strong> prop:</p>
<pre class="language-jsx"><code><span class="token tag"><span class="token tag"><span class="token punctuation"><</span><span class="token class-name">Routes</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">Route</span></span> <span class="token attr-name">path</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>user<span class="token punctuation">"</span></span> <span class="token attr-name">element</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span><span class="token class-name">UserLayout</span></span> <span class="token punctuation">/></span></span><span class="token punctuation">}</span></span> <span class="token punctuation">></span></span>
<span class="token punctuation">{</span><span class="token comment">/* show the UserHome at ``/user` */</span><span class="token punctuation">}</span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span><span class="token class-name">Route</span></span> <span class="token attr-name">index</span> <span class="token attr-name">element</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span><span class="token class-name">UserHome</span></span> <span class="token punctuation">/></span></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><span class="token class-name">Route</span></span> <span class="token attr-name">path</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>profile<span class="token punctuation">"</span></span> <span class="token attr-name">element</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span><span class="token class-name">UserProfile</span></span> <span class="token punctuation">/></span></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><span class="token class-name">Route</span></span> <span class="token attr-name">path</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>favorites<span class="token punctuation">"</span></span> <span class="token attr-name">element</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span><span class="token class-name">FavoriteItems</span></span> <span class="token punctuation">/></span></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><span class="token class-name">Route</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">Routes</span></span><span class="token punctuation">></span></span></code></pre>
<p>Notice that the <code>index</code> prop (which takes no other values!) in effect “replaces” the <code>path</code> segment for that child.</p>
<div class="alert alert-info">
It is often useful to specify the routes as a <code>const</code> variable (e.g., <code>routes</code>) that is an object containing paths and which component to render for that path. You can use the <code>useRoutes()</code> hook to then render this object <em>instead</em> of specifying a <code><Routes></code> element. This is only recommended for particularly large applications.
</div>
<p>You can use the <code>useMatch()</code> hook to get access to the current <code>path</code>; this can be useful for specifying e.g., relative image paths.</p>
</div>
<div id="url-parameters" class="section level4 unnumbered">
<h4>URL Parameters</h4>
<p>It is also possible to include <em>variables</em> in the matched route using what are called <strong>URL Parameters</strong>. As you may recall from <a href="https://info201.github.io/apis.html#uris">reading a RESTful API</a>, URI endpoints are often specified with “variables” written using <strong><code>:param</code></strong> syntax (a colon <code>:</code> followed by the parameter name). For example, the URI</p>
<pre><code>https://api.github.com/users/:username</code></pre>
<p>from the <a href="https://developer.github.com/v3/users/">Github API</a> refers to a particular user—you can <em>replace</em> <code>:username</code> with any value you want: <code>https://api.github.com/users/joelwross</code> refers to the <code>joelwross</code> user (so <code>username = 'joelwross'</code>), while <code>https://api.github.com/users/mkfreeman</code> refers to the <code>mkfreeman</code> user (so <code>username = 'mkfreeman'</code>).</p>
<p>React Router supports a similar syntax when specifying Route paths. For example:</p>
<pre class="language-jsx"><code><span class="token tag"><span class="token tag"><span class="token punctuation"><</span><span class="token class-name">Route</span></span> <span class="token attr-name">path</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">'</span>posts/:postId<span class="token punctuation">'</span></span> <span class="token attr-name">element</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</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 punctuation">/></span></span><span class="token punctuation">}</span></span> <span class="token punctuation">/></span></span></code></pre>
<p>will match a path that starts with <code>posts/</code> and is followed by any other path segment (e.g., <code>post/hello</code>, <code>post/2022-10-31</code>, etc). The <code>:postId</code> (because it starts with the leading <code>:</code>) will be treated as a parameter which will be assigned whatever value is part of the URI in that spot—so <code>post/hello</code> would have <code>'hello'</code> as the <code>postId</code>, and <code>post/2017-10-31</code> would have <code>'2017-10-31'</code> as the <code>postId</code>.</p>
<p>You can access the values assigned to the URL parameters by using the <strong><code>useParams</code></strong> hook provided by <code>react-router</code>. This hook returns an object whose keys are the parameter names and whose values are the param values:</p>
<pre class="language-jsx"><code><span class="token keyword">import</span> <span class="token punctuation">{</span> useParams <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'react-router'</span><span class="token punctuation">;</span>
<span class="token keyword">function</span> <span class="token function">BlogPost</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">//access the URL params as an object</span>
<span class="token comment">//it's also common to use object destructuring here</span>
<span class="token keyword">const</span> urlParams <span class="token operator">=</span> <span class="token function">useParams</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 punctuation">(</span>
<span class="token punctuation">{</span><span class="token comment">/* postId was the URL parameter from the above example! */</span><span class="token punctuation">}</span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>h1</span><span class="token punctuation">></span></span>You are looking at blog post <span class="token punctuation">{</span>urlParams<span class="token punctuation">.</span>postId<span class="token punctuation">}</span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>h1</span><span class="token punctuation">></span></span>
<span class="token punctuation">)</span>
<span class="token punctuation">}</span></code></pre>
<p>In the above <code>BlogPost</code> component, the <code>urlParams</code> value will be an object containing different values depending on the route:</p>
<ul>
<li>If the element is rendered by <code><Route path="posts/:postId" element={<BlogPost />} /></code>, then
<ul>
<li>visiting <code>posts/hello</code> will cause <code>urlParams</code> to be the object <code>{postId: "hello"}</code></li>
<li>visiting <code>posts/2022-10-31</code> will cause <code>urlParams</code> to be the object: <code>{postId: "2022-10-13"}</code></li>
</ul></li>
<li>If the element is rendered by <code><Route path="posts/:date/:title" element={<BlogPost />} /></code>, then
<ul>
<li>visiting <code>posts/2022-10-31/Hello</code> will cause <code>urlParams</code> to be the object <code>{date: "2022-10-31", title: "Hello"}</code> (note the multiple values for the multiple parameters!)</li>
</ul></li>
</ul>
<p>If you want to work with <strong>query parameters</strong> (e.g., the <code>?key1=value1&key2=value2</code> part of the URL), you can use the <code>useSearchParams()</code> hook. This works similar to the <code>useState()</code> hook, except that the value will be stored in the URL query parameter rather than in the Component’s state. Note that query parameters should only be used for values such as search queries that <em>don’t correspond to a consistent resource</em>.</p>
</div>
</div>
<div id="linking" class="section level3 unnumbered">
<h3>Linking</h3>
<p>While specifying <code><Route></code> elements will allow you to show different “pages” at different URLs, in order for a Single Page Application to function you need to be able to <em>navigate between routes</em> without causing the page to reload. Thus you can’t just use normal <code><a></code> elements to link between “pages”—browsers interpret clicking on <code><a></code> elements as a command to send a new HTTP request, and you instead just want to change the URL and re-render the App.</p>
<p>Instead, React Router provides a <strong><code><Link></code></strong> element that you can use to create a hyperlink to another route within the application. This component takes a <strong><code>to</code></strong> prop that you use to specify the route that it links to:</p>
<pre class="language-jsx"><code><span class="token tag"><span class="token tag"><span class="token punctuation"><</span><span class="token class-name">Link</span></span> <span class="token attr-name">to</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>about<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Click to visit the About Page<span class="token tag"><span class="token tag"><span class="token punctuation"></</span><span class="token class-name">Link</span></span><span class="token punctuation">></span></span></code></pre>
<ul>
<li><p>The component will render as an <code><a></code> element with a special <code>onClick</code> handler that keeps the browser from loading a new page. Thus you can specify any content that you would put in the <code><a></code> (such as the hyperlink text) as child content of the <code><Link></code>. Importantly: a <code><Link></code> is a <em>replacement</em> for an <code><a></code> element—do not try to put one inside of the other!</p></li>
<li><p>A <code>to</code> property that is <em>relative</em> path (so doesn’t have a starting <code>/</code>) will resolve relative to its parent route. Thus you can use <code>..</code> to refer to the parent route as you would with any other relative path.</p></li>
</ul>
<p>React Router also provides a <code><NavLink></code> Component. This works exactly like the <code><Link></code> component, except if the <code>to</code> route matches the <em>current route</em>, then the element will have the <code>active</code> CSS class added to it. This is used for example to have a navigation section “highlight” the link to the page you’re currently on, helping the user understand where they are on the page. It’s also possible to specify a callback function if you wish to use a custom name for the “active” class; see the documentation for an example (watch out of the <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Conditional_Operator">ternary operator</a>).</p>
<div id="redirecting" class="section level4 unnumbered">
<h4>Redirecting</h4>
<p>In addition to <code><Link></code> elements that allow the user to navigate by clicking an element, React Router also provides functionality to <em>programmatically</em> navigate through routes.</p>
<p>The primary tool for this is the <a href="https://reactrouter.com/en/6.4.4/hooks/use-navigate"><strong><code>useNavigate()</code></strong></a> hook. This hook, when called, will provide a function (conventionally named <code>navigate</code>) that can be called to redirect the App—to change the URL without reloading the page (and thus cause the Routes to re-render):</p>
<pre class="language-jsx"><code><span class="token keyword">import</span> <span class="token punctuation">{</span> useNavigate <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'react-router'</span><span class="token punctuation">;</span>
<span class="token comment">//A simple form component</span>
<span class="token keyword">function</span> <span class="token function">Form</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> navigate <span class="token operator">=</span> <span class="token function">useNavigate</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//access navigate function</span>
<span class="token comment">//event handler for the form</span>
<span class="token keyword">const</span> <span class="token function-variable function">handleSubmit</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>
event<span class="token punctuation">.</span><span class="token function">preventDefault</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">//do form submission work here</span>
<span class="token function">navigate</span><span class="token punctuation">(</span><span class="token string">"/home"</span><span class="token punctuation">)</span> <span class="token comment">//navigate to the `/home` route</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>form</span> <span class="token attr-name">onSubmit</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span>handleSubmit<span class="token punctuation">}</span></span><span class="token punctuation">></span></span> <span class="token operator">...</span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>form</span><span class="token punctuation">></span></span>
<span class="token punctuation">)</span>
<span class="token punctuation">}</span></code></pre>
<p>The <code>navigate()</code> function takes an an argument the same stying you would use as the <code>to</code> prop for a <code><Link></code> element.</p>
<ul>
<li><p>You should only use the <code>navigate()</code> function when <em>non-navigation</em> actions (such as form submissions) need to cause redirections. If the user is clicking on an element to navigate, just embed that element in a <code><Link></code>—that will keep your page <strong>accessible</strong>.</p></li>
<li><p>Additionally, only call <code>navigate()</code> from inside of an event handler; don’t use it in the body of a Compnent function—use a <code><Navigate></code> element.</p></li>
</ul>
<p>Alternatively, you can cause the route to change by rendering a <a href="https://reactrouter.com/en/6.4.4/components/navigate"><strong><code>Navigate</code></strong></a> element. This element accepts a <code>to</code> prop just like a <code><Link></code>, and when rendered will redirect the user as if the link were clicked without the user doing anything.</p>
<p>To be clear: you need to <em>render</em> the <code><Navigate></code> element—to <code>return</code> it from a Component as the DOM to render. So instead of a component returning e.g., <code><div></code>, you would have it return a <code><Navigate></code>. Thus you would use this element with conditional rendering, using an <code>if</code> statement to determine whether you want to return/show regular DOM content or instead return a <code><Navigate></code> to redirect.</p>
<ul>
<li><em>DO NOT</em> render a <code><Navigate></code> as the child of displayed content (e.g., inside a <code><div></code>), as this can cause issues with the redirect taking multiple “DOM update cycles” to process, interfering with your application’s processing. Instead, determine whether you should redirect and if so <code>return</code> just the <code><Navigate></code> element (e.g., with a “break early” sentinel condition).</li>
</ul>
<p><code><Navigate></code> elements are particular useful when creating “protected routes”—routes that are only accessible under certain conditions (such as if the user is logged in). To do this, you have the Route’s <code>element</code> include an <code>if</code> statement to determine whether it should display content, or if it instead should show the <code><Navigate></code> and this redirect:</p>
<pre class="language-jsx"><code><span class="token keyword">function</span> <span class="token function">ProtectedPage</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">//...determine if user is logged in (eg., via AJAX)</span>
<span class="token keyword">if</span><span class="token punctuation">(</span><span class="token operator">!</span>userIsLoggedIn<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">//if no user, send to sign in</span>
<span class="token keyword">return</span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span><span class="token class-name">Navigate</span></span> <span class="token attr-name">to</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/signin<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">//otherwise show content</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 keyword">protected</span> content<span class="token operator">!</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>A nice strategy is to combine the above logic with a <em>nested route</em>, allowing you to re-use authentication logic across your app:</p>
<pre class="language-jsx"><code><span class="token keyword">function</span> <span class="token function">RequireAuth</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">//...determine if user is logged in (eg., via AJAX)</span>
<span class="token keyword">if</span><span class="token punctuation">(</span><span class="token operator">!</span>userIsLoggedIn<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">//if no user, send to sign in</span>
<span class="token keyword">return</span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span><span class="token class-name">Navigate</span></span> <span class="token attr-name">to</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/signin<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">else</span> <span class="token punctuation">{</span> <span class="token comment">//otherwise, show the child route content</span>
<span class="token keyword">return</span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span><span class="token class-name">Outlet</span></span> <span class="token punctuation">/></span></span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token keyword">function</span> <span class="token function">App</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">return</span> <span class="token punctuation">(</span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span><span class="token class-name">Routes</span></span><span class="token punctuation">></span></span>
<span class="token punctuation">{</span><span class="token comment">/* protected routes */</span><span class="token punctuation">}</span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span><span class="token class-name">Route</span></span> <span class="token attr-name">element</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span><span class="token class-name">RequireAuth</span></span> <span class="token punctuation">/></span></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><span class="token class-name">Route</span></span> <span class="token attr-name">path</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>profile<span class="token punctuation">"</span></span> <span class="token attr-name">element</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span><span class="token class-name">ProfilePage</span></span> <span class="token punctuation">/></span></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><span class="token class-name">Route</span></span> <span class="token attr-name">path</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>secret<span class="token punctuation">"</span></span> <span class="token attr-name">element</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span><span class="token class-name">SecretPage</span></span> <span class="token punctuation">/></span></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><span class="token class-name">Route</span></span><span class="token punctuation">></span></span>
<span class="token punctuation">{</span><span class="token comment">/* public routes */</span><span class="token punctuation">}</span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span><span class="token class-name">Route</span></span> <span class="token attr-name">path</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>signin<span class="token punctuation">"</span></span> <span class="token attr-name">element</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span><span class="token class-name">SignInPage</span></span> <span class="token punctuation">/></span></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><span class="token class-name">Routes</span></span><span class="token punctuation">></span></span>
<span class="token punctuation">)</span>
<span class="token punctuation">}</span></code></pre>
<p>The Route rendering the <code><RequireAuth></code> has no defined <code>path</code>, defaulting to <code>""</code> (thus not providing a segment to consider). So if its child route are matched, that component will render, and either use the <code><Navigate></code> to redirect to a public route, or to show the child route element in place of the <code><Outlet></code>. This structure lets you keep your protected routes organized, while keeping all of your “user is logged in” logic in a single location.</p>
</div>
</div>
<div id="react-router-and-hosting" class="section level3 unnumbered">
<h3>React Router and Hosting</h3>
<p>React Router’s client-side routing introduce a few additional considerations when the you wish to deploy your app on a non-development server, such as Github Pages (e.g., what happens when you deploy a Vite project).</p>
<p><em>First</em>, consider what happens when you type a route (e.g., <code>https://domain.com/about</code> to access the <code>/about</code> route) into the browser’s URL bar in order to navigate to it. This creates an HTTP Request for the resource at the URI with an <code>/about</code> path. When that request is received by the web server, that server will perform <em>server-side routing</em> and attempt to access the resource at that location (e.g., it will look for an <code>/about/index.html</code> page). But this isn’t what you want to happen—because there is no content at that resource (no <code>/about/index.html</code>), the server will return a <a href="https://http.cat/404">404</a> error.</p>
<p>Instead, you want the server to take the request for the <code>/about</code> resource and <em>instead</em> return your root <code>/index.html</code> page, but with the appropriate JavaScript code which will allow the <em>client-side routing</em> to change the browser’s URL bar and show the content at the <code>/about</code> route. In effect, you want the server to be able to return your root <code>index.html</code> page no matter what route is specified in the HTTP Request!</p>
<p>It is perfectly possible to have a web server do this (to <em>not</em> perform server-side routing and instead always return <code>/index.html</code> no matter what resource is requested); indeed, this is what the Create React App development server does. However GitHub Pages doesn’t have this functionality: if you send an HTTP request for a resource that doesn’t exist (e.g., <code>/about</code>), you will receive a 404 error. There are a few ways to work around this:</p>
<ol style="list-style-type: decimal">
<li><p>You can use a <code><HashRouter></code> instead of a <code><BrowserRouter></code> The <code><HashRouter></code> uses the <a href="https://en.wikipedia.org/wiki/Fragment_identifier">fragment identifier</a> portion of the URI to record and track which route the user is viewing: the HTTP request is thus sent to <code>https://domain.com/index.html#/about</code> to get the <code>/about</code> route—and since <code>index.html</code> is the default resource, this can be abbreviated to <code>https://domain.com/#/about</code>, which is <em>almost</em> as good. In this way you are always requesting the appropriate resource (<code>/index.html</code>), but can still perform client-side routing. The trade-off is that your URLs will have extraneous <code>#</code> symbols in them (which also makes utilizing inner-page navigation with the fragment more difficult), and going to <code>domain.com/about</code> will <em>still</em> cause a 404 error. It’s recommend that you <strong>avoid</strong> this element if possible.</p></li>
<li><p>Another approach is to replace your server’s 404 page with something that goes to your <code>index.html</code> (using <em>server-side routing</em>)—so instead of the user being shown the 404, they are shown your <code>index.html</code> which is about to do the client-side routing! <a href="https://github.com/rafrex/spa-github-pages"><code>spa-github-pages</code></a> provides some boilerplate for doing this with GitHub Pages, but it is a “hacky” approach and so is also not recommended.</p></li>
<li><p>The <strong>best and correct</strong> approach is to use a web hosting system that better supports the server-side routing needed for single-page applications. For example, <a href="https://firebase.google.com/docs/hosting/">Firebase Hosting</a> allows you to specify a <a href="https://firebase.google.com/docs/hosting/url-redirects-rewrites#section-rewrites">rewrite rule</a> that will cause the server to return your <code>index.html</code> no matter which route the HTTP Request specifies. Create React App provides <a href="https://create-react-app.dev/docs/deployment/#firebase">instructions</a> on deploying to Firebase Hosting, including a simple wizard configuration that allows you to configure your site as a single-page application.</p></li>
</ol>
<!-- _Second_, in addition to the server-side routing issue, you will need to do extra work to handle `<Redirect>` elements if your application's URL is in a _subresource_ of the server (e.g., it can be found at `https://domain.com/app/index.html`). While `<Link>` elements will route correctly in this case (`<Link to='/home'>` will go to `https://domain.com/app/home`), `<Redirect>` elements will _overwrite_ the path part of the URI: `<Redirect to='/home'>` will take you to to `https://domain.com/home`, losing the fact that your application is in `/app` resource.
Luckily, it is easy to support this behavior and tell React Router that all paths should be treated relative to that subresource (relative to the `/app` path). You do this by passing the [**`basename`**](https://reacttraining.com/react-router/web/api/BrowserRouter/basename-string) prop to the `<Router>`:
```jsx
<BrowserRouter basename={process.env.PUBLIC_URL+'/'}>
```
- This example specifies that the "base" uri should be whatever URI was listed in the `"homepage"` key of the project's `package.json` folder, such as what you specifying when [deploying Create React App to Github Pages](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#github-pages). You would want to use that exact expression (`process.env.PUBLIC_URL`), which is a global variable referring to the _env_ironment of the bundling node process; the `PUBLIC_URL` key is assigned the `homepage` property by Create React App. -->
</div>
</div>
<div id="resources-14" class="section level2 unnumbered">
<h2>Resources</h2>
<div class="list-condensed">
<ul>
<li><a href="https://reactrouter.com/start/library/installation">React Router Documentation</a> - includes tutorials and examples</li>
<li><a href="https://api.reactrouter.com/v7/">React Router API</a> - complete list of Components and hooks</li>
</ul>
</div>
</div>
</div>
</section>
</div>
</div>
</div>
<a href="interactive-react.html" class="navigation navigation-prev " aria-label="Previous page"><i class="fa fa-angle-left"></i></a>
<a href="ajax.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/router.Rmd",
"text": "Edit"
},
"history": {
"link": null,
"text": null
},
"view": {
"link": null,
"text": null
},
"download": null,
"search": {
"engine": "fuse",
"options": null
},
"toc": {
"collapse": "section",
"scroll_highlight": true
}
});
});
</script>
<!-- dynamically load mathjax for compatibility with self-contained -->
<script>
(function () {
var script = document.createElement("script");
script.type = "text/javascript";
var src = "true";
if (src === "" || src === "true") src = "https://mathjax.rstudio.com/latest/MathJax.js?config=TeX-MML-AM_CHTML";
if (location.protocol !== "file:")
if (/^https?:/.test(src))
src = src.replace(/^https?:/, '');
script.src = src;
document.getElementsByTagName("head")[0].appendChild(script);
})();
</script>
</body>
</html>