812 lines
62 KiB
HTML
812 lines
62 KiB
HTML
<!DOCTYPE HTML>
|
||
<html lang="en" class="coal" dir="ltr">
|
||
<head>
|
||
<!-- Book generated using mdBook -->
|
||
<meta charset="UTF-8">
|
||
<title>react router - Andrew's Blog</title>
|
||
|
||
|
||
<!-- Custom HTML head -->
|
||
|
||
<meta name="description" content="Andrew Ryan's Blog">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
<meta name="theme-color" content="#ffffff">
|
||
|
||
<link rel="icon" href="../../favicon.svg">
|
||
<link rel="shortcut icon" href="../../favicon.png">
|
||
<link rel="stylesheet" href="../../css/variables.css">
|
||
<link rel="stylesheet" href="../../css/general.css">
|
||
<link rel="stylesheet" href="../../css/chrome.css">
|
||
|
||
<!-- Fonts -->
|
||
<link rel="stylesheet" href="../../FontAwesome/css/font-awesome.css">
|
||
<link rel="stylesheet" href="../../fonts/fonts.css">
|
||
|
||
<!-- Highlight.js Stylesheets -->
|
||
<link rel="stylesheet" href="../../highlight.css">
|
||
<link rel="stylesheet" href="../../tomorrow-night.css">
|
||
<link rel="stylesheet" href="../../ayu-highlight.css">
|
||
|
||
<!-- Custom theme stylesheets -->
|
||
<link rel="stylesheet" href="../../src/style/custom.css">
|
||
|
||
<!-- MathJax -->
|
||
<script async src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
|
||
</head>
|
||
<body class="sidebar-visible no-js">
|
||
<div id="body-container">
|
||
<!-- Provide site root to javascript -->
|
||
<script>
|
||
var path_to_root = "../../";
|
||
var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "coal" : "coal";
|
||
</script>
|
||
|
||
<!-- Work around some values being stored in localStorage wrapped in quotes -->
|
||
<script>
|
||
try {
|
||
var theme = localStorage.getItem('mdbook-theme');
|
||
var sidebar = localStorage.getItem('mdbook-sidebar');
|
||
|
||
if (theme.startsWith('"') && theme.endsWith('"')) {
|
||
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
|
||
}
|
||
|
||
if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
|
||
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
|
||
}
|
||
} catch (e) { }
|
||
</script>
|
||
|
||
<!-- Set the theme before any content is loaded, prevents flash -->
|
||
<script>
|
||
var theme;
|
||
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
|
||
if (theme === null || theme === undefined) { theme = default_theme; }
|
||
var html = document.querySelector('html');
|
||
html.classList.remove('coal')
|
||
html.classList.add(theme);
|
||
var body = document.querySelector('body');
|
||
body.classList.remove('no-js')
|
||
body.classList.add('js');
|
||
</script>
|
||
|
||
<input type="checkbox" id="sidebar-toggle-anchor" class="hidden">
|
||
|
||
<!-- Hide / unhide sidebar before it is displayed -->
|
||
<script>
|
||
var body = document.querySelector('body');
|
||
var sidebar = null;
|
||
var sidebar_toggle = document.getElementById("sidebar-toggle-anchor");
|
||
if (document.body.clientWidth >= 1080) {
|
||
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
|
||
sidebar = sidebar || 'visible';
|
||
} else {
|
||
sidebar = 'hidden';
|
||
}
|
||
sidebar_toggle.checked = sidebar === 'visible';
|
||
body.classList.remove('sidebar-visible');
|
||
body.classList.add("sidebar-" + sidebar);
|
||
</script>
|
||
|
||
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
|
||
<div class="sidebar-scrollbox">
|
||
<ol class="chapter"><li class="chapter-item affix "><a href="../../index.html">Andrew's Blog</a></li><li class="chapter-item "><a href="../../posts/linux/linux.html"><strong aria-hidden="true">1.</strong> linux</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="../../posts/linux/install_linux.html"><strong aria-hidden="true">1.1.</strong> install linux</a></li><li class="chapter-item "><a href="../../posts/linux/bash_profile.html"><strong aria-hidden="true">1.2.</strong> bash profile</a></li><li class="chapter-item "><a href="../../posts/linux/command_list.html"><strong aria-hidden="true">1.3.</strong> command list</a></li><li class="chapter-item "><a href="../../posts/linux/git_guide.html"><strong aria-hidden="true">1.4.</strong> git guide</a></li><li class="chapter-item "><a href="../../posts/linux/tar.html"><strong aria-hidden="true">1.5.</strong> tar</a></li><li class="chapter-item "><a href="../../posts/linux/run_x86_elf_in_x64_setup.html"><strong aria-hidden="true">1.6.</strong> run x86 elf in x64 setup</a></li></ol></li><li class="chapter-item "><a href="../../posts/mac/mac.html"><strong aria-hidden="true">2.</strong> mac</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="../../posts/mac/macos_profiles.html"><strong aria-hidden="true">2.1.</strong> macos profiles</a></li></ol></li><li class="chapter-item "><a href="../../posts/swift/swift.html"><strong aria-hidden="true">3.</strong> swift</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="../../posts/swift/learn_swift.html"><strong aria-hidden="true">3.1.</strong> learn swift basics</a></li><li class="chapter-item "><a href="../../posts/swift/swift_extensions.html"><strong aria-hidden="true">3.2.</strong> Swift extensions</a></li><li class="chapter-item "><a href="../../posts/swift/swiftui_extension.html"><strong aria-hidden="true">3.3.</strong> SwiftUI extensions</a></li><li class="chapter-item "><a href="../../posts/swift/install_swift.html"><strong aria-hidden="true">3.4.</strong> install swift</a></li><li class="chapter-item "><a href="../../posts/swift/task_planner.html"><strong aria-hidden="true">3.5.</strong> implment task panner app with SwiftUI</a></li><li class="chapter-item "><a href="../../posts/swift/swift_cheat_sheet.html"><strong aria-hidden="true">3.6.</strong> Swift Cheat Sheet</a></li><li class="chapter-item "><a href="../../posts/swift/yinci_url.html"><strong aria-hidden="true">3.7.</strong> Personal privacy protocol</a></li><li class="chapter-item "><a href="../../posts/swift/swift_regular_exressions.html"><strong aria-hidden="true">3.8.</strong> Swift regular exressions</a></li><li class="chapter-item "><a href="../../posts/ios/how_to_create_beautiful_ios_charts_in_swift.html"><strong aria-hidden="true">3.9.</strong> How to Create Beautiful iOS Charts in鑱絊wift</a></li><li class="chapter-item "><a href="../../posts/swift/swiftui_source_code.html"><strong aria-hidden="true">3.10.</strong> SwiftUI source code</a></li><li class="chapter-item "><a href="../../posts/swift/use_swift_fetch_iciba_api.html"><strong aria-hidden="true">3.11.</strong> use swift fetch iciba API</a></li></ol></li><li class="chapter-item "><a href="../../posts/ios/ios.html"><strong aria-hidden="true">4.</strong> ios</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="../../posts/ios/cocaposd_setup_and_install_for_ios_project.html"><strong aria-hidden="true">4.1.</strong> cocaposd setup and install for ios project</a></li><li class="chapter-item "><a href="../../posts/ios/swiftui_show_gif_image.html"><strong aria-hidden="true">4.2.</strong> SwiftUI show gif image</a></li><li class="chapter-item "><a href="../../posts/ios/implement_task_planner_app.html"><strong aria-hidden="true">4.3.</strong> implement Task planner App</a></li></ol></li><li class="chapter-item "><a href="../../posts/objective_c/objective_c.html"><strong aria-hidden="true">5.</strong> objective_c</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="../../posts/objective_c/objective_c_cheat_sheet.html"><strong aria-hidden="true">5.1.</strong> Objective-C Cheat Sheet</a></li><li class="chapter-item "><a href="../../posts/objective_c/objective_c_for_absolute_beginners_read_note.html"><strong aria-hidden="true">5.2.</strong> Objective-C Note</a></li></ol></li><li class="chapter-item "><a href="../../posts/dart/dart.html"><strong aria-hidden="true">6.</strong> dart</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="../../posts/dart/flutter.html"><strong aria-hidden="true">6.1.</strong> Flutter Cheat Sheet</a></li><li class="chapter-item "><a href="../../posts/dart/dart_cheat_sheet.html"><strong aria-hidden="true">6.2.</strong> Dart Cheat Sheet</a></li><li class="chapter-item "><a href="../../posts/flutter/flutter_dev_test.html"><strong aria-hidden="true">6.3.</strong> Flutter dev test</a></li></ol></li><li class="chapter-item "><a href="../../posts/rust/rust.html"><strong aria-hidden="true">7.</strong> rust</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="../../posts/rust/offline_use_rust.html"><strong aria-hidden="true">7.1.</strong> Offline use rust</a></li><li class="chapter-item "><a href="../../posts/rust/rust_grammer.html"><strong aria-hidden="true">7.2.</strong> rust grammar</a></li><li class="chapter-item "><a href="../../posts/rust/pase_string_and_decimal_conversion.html"><strong aria-hidden="true">7.3.</strong> pase string and decimal conversion</a></li><li class="chapter-item "><a href="../../posts/rust/parse_types.html"><strong aria-hidden="true">7.4.</strong> rust types</a></li><li class="chapter-item "><a href="../../posts/rust/rust_life_cycle.html"><strong aria-hidden="true">7.5.</strong> Rust life cycle</a></li><li class="chapter-item "><a href="../../posts/rust/rust_generic.html"><strong aria-hidden="true">7.6.</strong> rust generics</a></li><li class="chapter-item "><a href="../../posts/rust/rust_implment_matrix.html"><strong aria-hidden="true">7.7.</strong> Rust implement matrix</a></li><li class="chapter-item "><a href="../../posts/rust/rust_sort.html"><strong aria-hidden="true">7.8.</strong> Rust implement sort algorithms</a></li><li class="chapter-item "><a href="../../posts/rust/implement_aes_encryption.html"><strong aria-hidden="true">7.9.</strong> Rust implement AEC encryption and decryption</a></li><li class="chapter-item "><a href="../../posts/rust/implement_trie_data_structure.html"><strong aria-hidden="true">7.10.</strong> implement trie data structure</a></li><li class="chapter-item "><a href="../../posts/rust/rust_implement_tree.html"><strong aria-hidden="true">7.11.</strong> implement tree data_structure</a></li><li class="chapter-item "><a href="../../posts/rust/list_dir.html"><strong aria-hidden="true">7.12.</strong> list dir</a></li><li class="chapter-item "><a href="../../posts/rust/fast_way_to_implment_object_trait.html"><strong aria-hidden="true">7.13.</strong> fast way to implment object trait</a></li><li class="chapter-item "><a href="../../posts/rust/compress_rust_binary_size.html"><strong aria-hidden="true">7.14.</strong> compress rust binary size</a></li><li class="chapter-item "><a href="../../posts/rust/implment_file_upload_backend.html"><strong aria-hidden="true">7.15.</strong> impliment file upload</a></li><li class="chapter-item "><a href="../../posts/rust/this_is_add_post_cli_implementation_in_rust.html"><strong aria-hidden="true">7.16.</strong> this is add_post cli implementation in rust</a></li><li class="chapter-item "><a href="../../posts/rust/use_rust_implment_a_copyclipbord_cli.html"><strong aria-hidden="true">7.17.</strong> Use rust implment a copyclipbord CLI</a></li><li class="chapter-item "><a href="../../posts/rust/sqlite_database_add_delete_update_show_in_rust.html"><strong aria-hidden="true">7.18.</strong> sqlite database add delete update show in rust</a></li><li class="chapter-item "><a href="../../posts/rust/implementing_tokio_joinhandle_for_wasm.html"><strong aria-hidden="true">7.19.</strong> Implementing tokio JoinHandle for wasm</a></li><li class="chapter-item "><a href="../../posts/rust/rust_implement_a_crate_for_encode_and_decode_brainfuck_and_ook.html"><strong aria-hidden="true">7.20.</strong> rust implement a crate for encode and decode brainfuck and ook</a></li><li class="chapter-item "><a href="../../posts/rust/slint_builtin_elements.html"><strong aria-hidden="true">7.21.</strong> Slint Builtin Elements</a></li><li class="chapter-item "><a href="../../posts/rust/corporate_network_install_rust_on_windows.html"><strong aria-hidden="true">7.22.</strong> Corporate network install Rust on windows</a></li><li class="chapter-item "><a href="../../posts/rust/rust_binary_file_how_to_judge_static_link_or_dynamic_link_in_macos.html"><strong aria-hidden="true">7.23.</strong> rust binary file how to judge static link or dynamic link in Macos</a></li><li class="chapter-item "><a href="../../posts/rust/rust_binary_include_dir_and_get_contents.html"><strong aria-hidden="true">7.24.</strong> rust binary include dir and get contents</a></li><li class="chapter-item "><a href="../../posts/rust/rust_logger_non-block.html"><strong aria-hidden="true">7.25.</strong> rust logger non-block</a></li><li class="chapter-item "><a href="../../posts/rust/rust_connect_sql_server_database.html"><strong aria-hidden="true">7.26.</strong> rust connect sql server database</a></li><li class="chapter-item "><a href="../../posts/rust/rust_websocket_implment.html"><strong aria-hidden="true">7.27.</strong> rust websocket implment</a></li></ol></li><li class="chapter-item "><a href="../../posts/java/java.html"><strong aria-hidden="true">8.</strong> java</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="../../posts/java/java_grammar.html"><strong aria-hidden="true">8.1.</strong> java grammar and codewar</a></li><li class="chapter-item "><a href="../../posts/java/run_jar.html"><strong aria-hidden="true">8.2.</strong> java run .jar</a></li><li class="chapter-item "><a href="../../posts/java/java_pomxml_add_defaultgoal_to_build.html"><strong aria-hidden="true">8.3.</strong> Java pomxml add defaultGoal to build</a></li><li class="chapter-item "><a href="../../posts/java/java_set_mvn_mirror.html"><strong aria-hidden="true">8.4.</strong> Java set mvn mirror</a></li></ol></li><li class="chapter-item "><a href="../../posts/python/python.html"><strong aria-hidden="true">9.</strong> python</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="../../posts/python/convert_pesn.html"><strong aria-hidden="true">9.1.</strong> convert pesn</a></li><li class="chapter-item "><a href="../../posts/python/find_remove_dir.html"><strong aria-hidden="true">9.2.</strong> find and remove dir</a></li><li class="chapter-item "><a href="../../posts/python/timing_message.html"><strong aria-hidden="true">9.3.</strong> wechat send message</a></li><li class="chapter-item "><a href="../../posts/python/use_python_openpyxl_package_read_and_edit_excel_files.html"><strong aria-hidden="true">9.4.</strong> Use python openpyxl package read and edit excel files</a></li></ol></li><li class="chapter-item "><a href="../../posts/go/go.html"><strong aria-hidden="true">10.</strong> go</a></li><li class="chapter-item "><a href="../../posts/js/js.html"><strong aria-hidden="true">11.</strong> js</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="../../posts/js/js_tutorial.html"><strong aria-hidden="true">11.1.</strong> js tutorial</a></li><li class="chapter-item "><a href="../../posts/js/js_tutorial_map.html"><strong aria-hidden="true">11.2.</strong> ja map</a></li><li class="chapter-item "><a href="../../posts/js/js_tutorial_math.html"><strong aria-hidden="true">11.3.</strong> js math</a></li><li class="chapter-item "><a href="../../posts/js/js_tutorial_object.html"><strong aria-hidden="true">11.4.</strong> js object</a></li><li class="chapter-item "><a href="../../posts/js/js_tutorial_set.html"><strong aria-hidden="true">11.5.</strong> js set</a></li><li class="chapter-item "><a href="../../posts/js/single_thread_and_asynchronous.html"><strong aria-hidden="true">11.6.</strong> single thread and asynchronous</a></li><li class="chapter-item "><a href="../../posts/js/this.html"><strong aria-hidden="true">11.7.</strong> js this</a></li><li class="chapter-item "><a href="../../posts/js/js_implment_aes.html"><strong aria-hidden="true">11.8.</strong> js implment aes</a></li><li class="chapter-item "><a href="../../posts/js/getting_started_with_ajax.html"><strong aria-hidden="true">11.9.</strong> getting started with ajax</a></li><li class="chapter-item "><a href="../../posts/js/BinarySearchTree.html"><strong aria-hidden="true">11.10.</strong> binary search tree</a></li><li class="chapter-item "><a href="../../posts/js/goole_zx.html"><strong aria-hidden="true">11.11.</strong> goole zx</a></li><li class="chapter-item "><a href="../../posts/js/es6.html"><strong aria-hidden="true">11.12.</strong> es6</a></li></ol></li><li class="chapter-item "><a href="../../posts/ruby/ruby.html"><strong aria-hidden="true">12.</strong> ruby</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="../../posts/ruby/rails_setup_env.html"><strong aria-hidden="true">12.1.</strong> ruby on rails setup environment</a></li><li class="chapter-item "><a href="../../posts/ruby/learn_ruby.html"><strong aria-hidden="true">12.2.</strong> learn ruby</a></li><li class="chapter-item "><a href="../../posts/ruby/ruby_note.html"><strong aria-hidden="true">12.3.</strong> Ruby Note</a></li><li class="chapter-item "><a href="../../posts/ruby/setup_ruby_for_ctf.html"><strong aria-hidden="true">12.4.</strong> Setup ruby for CTF</a></li></ol></li><li class="chapter-item expanded "><a href="../../posts/react/react.html"><strong aria-hidden="true">13.</strong> react</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="../../posts/react/react_life_cycle.html"><strong aria-hidden="true">13.1.</strong> react life cycle</a></li><li class="chapter-item expanded "><a href="../../posts/react/react_router.html" class="active"><strong aria-hidden="true">13.2.</strong> react router</a></li><li class="chapter-item "><a href="../../posts/react/react_this.html"><strong aria-hidden="true">13.3.</strong> react this</a></li><li class="chapter-item "><a href="../../posts/react/react_interviw.html"><strong aria-hidden="true">13.4.</strong> react interview</a></li><li class="chapter-item "><a href="../../posts/react/important_react_interview.html"><strong aria-hidden="true">13.5.</strong> important react interview</a></li><li class="chapter-item "><a href="../../posts/react/react_quick_reference.html"><strong aria-hidden="true">13.6.</strong> react quick reference</a></li><li class="chapter-item "><a href="../../posts/react/redux_quick_reference.html"><strong aria-hidden="true">13.7.</strong> redux quick reference</a></li></ol></li><li class="chapter-item "><a href="../../posts/vue/vue.html"><strong aria-hidden="true">14.</strong> vue</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="../../posts/vue/vue_ajax.html"><strong aria-hidden="true">14.1.</strong> vue ajax</a></li></ol></li><li class="chapter-item "><a href="../../posts/angular/angular.html"><strong aria-hidden="true">15.</strong> angular</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="../../posts/angular/controller_communication.html"><strong aria-hidden="true">15.1.</strong> controller communication</a></li><li class="chapter-item "><a href="../../posts/angular/creating_custom_directives.html"><strong aria-hidden="true">15.2.</strong> creating custom directives</a></li><li class="chapter-item "><a href="../../posts/angular/directive_notes.html"><strong aria-hidden="true">15.3.</strong> directive notes</a></li><li class="chapter-item "><a href="../../posts/angular/directive_communication.html"><strong aria-hidden="true">15.4.</strong> directive communication</a></li><li class="chapter-item "><a href="../../posts/angular/post_params.html"><strong aria-hidden="true">15.5.</strong> post params</a></li><li class="chapter-item "><a href="../../posts/angular/read_json_angular.html"><strong aria-hidden="true">15.6.</strong> read json angular</a></li><li class="chapter-item "><a href="../../posts/angular/same_route_reload.html"><strong aria-hidden="true">15.7.</strong> same route reload</a></li></ol></li><li class="chapter-item "><a href="../../posts/css/css.html"><strong aria-hidden="true">16.</strong> css</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="../../posts/css/use_css_media.html"><strong aria-hidden="true">16.1.</strong> use css media</a></li></ol></li><li class="chapter-item "><a href="../../posts/php/php.html"><strong aria-hidden="true">17.</strong> php</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="../../posts/php/for_php_string_implment_some_extemtion_functions.html"><strong aria-hidden="true">17.1.</strong> for php string implment some extemtion functions</a></li><li class="chapter-item "><a href="../../posts/php/php_cheatsheet.html"><strong aria-hidden="true">17.2.</strong> PHP cheatsheet</a></li></ol></li><li class="chapter-item "><a href="../../posts/leetcode/leetcode.html"><strong aria-hidden="true">18.</strong> leetcode</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="../../posts/leetcode/rust_leetcode.html"><strong aria-hidden="true">18.1.</strong> rust leetcode</a></li><li class="chapter-item "><a href="../../posts/leetcode/rust_codewar.html"><strong aria-hidden="true">18.2.</strong> rust codewar</a></li><li class="chapter-item "><a href="../../posts/leetcode/swift_codewar.html"><strong aria-hidden="true">18.3.</strong> swift codewar</a></li><li class="chapter-item "><a href="../../posts/leetcode/js_leetcode.html"><strong aria-hidden="true">18.4.</strong> js leetcode</a></li><li class="chapter-item "><a href="../../posts/leetcode/java_leetcode.html"><strong aria-hidden="true">18.5.</strong> java leetcode</a></li><li class="chapter-item "><a href="../../posts/leetcode/rust_huawei.html"><strong aria-hidden="true">18.6.</strong> huawei test</a></li><li class="chapter-item "><a href="../../posts/leetcode/rust_utils.html"><strong aria-hidden="true">18.7.</strong> rust common functions</a></li><li class="chapter-item "><a href="../../posts/leetcode/olympiad_training.html"><strong aria-hidden="true">18.8.</strong> Computer olympiad training</a></li></ol></li><li class="chapter-item "><a href="../../posts/ctf/CTF.html"><strong aria-hidden="true">19.</strong> ctf</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="../../posts/ctf/CTF_Note.html"><strong aria-hidden="true">19.1.</strong> CTF Note</a></li><li class="chapter-item "><a href="../../posts/ctf/0.1_Web.html"><strong aria-hidden="true">19.2.</strong> Web</a></li><li class="chapter-item "><a href="../../posts/ctf/4.1_Misc.html"><strong aria-hidden="true">19.3.</strong> Misc</a></li><li class="chapter-item "><a href="../../posts/ctf/3.2_PWN_note.html"><strong aria-hidden="true">19.4.</strong> PWN</a></li><li class="chapter-item "><a href="../../posts/ctf/3.1_Crypto.html"><strong aria-hidden="true">19.5.</strong> Crypto</a></li><li class="chapter-item "><a href="../../posts/ctf/3.4_RSA_note.html"><strong aria-hidden="true">19.6.</strong> Rsa attack</a></li><li class="chapter-item "><a href="../../posts/ctf/3.5_Base64.html"><strong aria-hidden="true">19.7.</strong> Base64</a></li><li class="chapter-item "><a href="../../posts/ctf/0.0_SQL Injection Cheatsheet.html"><strong aria-hidden="true">19.8.</strong> SQL Injection Cheatsheet</a></li><li class="chapter-item "><a href="../../posts/ctf/1.1_SQL_injection.html"><strong aria-hidden="true">19.9.</strong> SQL Injection</a></li><li class="chapter-item "><a href="../../posts/ctf/1.2_SQL_injection_UNION_attacks.html"><strong aria-hidden="true">19.10.</strong> SQL Injection UNION attacks</a></li><li class="chapter-item "><a href="../../posts/ctf/1.3_Blind SQL injection.html"><strong aria-hidden="true">19.11.</strong> Blind SQL Injection</a></li><li class="chapter-item "><a href="../../posts/ctf/1.4_Code Injection.html"><strong aria-hidden="true">19.12.</strong> Code Injection</a></li><li class="chapter-item "><a href="../../posts/ctf/1.5_SSRF.html"><strong aria-hidden="true">19.13.</strong> SSRF</a></li><li class="chapter-item "><a href="../../posts/ctf/1.6_OS command injection.html"><strong aria-hidden="true">19.14.</strong> OS command injection</a></li><li class="chapter-item "><a href="../../posts/ctf/1.7_Local file inclusion.html"><strong aria-hidden="true">19.15.</strong> Local file inclusion</a></li><li class="chapter-item "><a href="../../posts/ctf/1.8_Remote file inclusion.html"><strong aria-hidden="true">19.16.</strong> Remote file inclusion</a></li><li class="chapter-item "><a href="../../posts/ctf/1.9_CSRFm.html"><strong aria-hidden="true">19.17.</strong> CSRF</a></li><li class="chapter-item "><a href="../../posts/ctf/1.10_NoSQL injection.html"><strong aria-hidden="true">19.18.</strong> NoSQL injection</a></li><li class="chapter-item "><a href="../../posts/ctf/1.11_JSON injection.html"><strong aria-hidden="true">19.19.</strong> JSON injection</a></li><li class="chapter-item "><a href="../../posts/ctf/1.12_CTF_Web_SQL_Note.html"><strong aria-hidden="true">19.20.</strong> CTF Web SQL Note</a></li><li class="chapter-item "><a href="../../posts/ctf/2.1_XXE.html"><strong aria-hidden="true">19.21.</strong> XXE</a></li><li class="chapter-item "><a href="../../posts/ctf/2.2_XSS.html"><strong aria-hidden="true">19.22.</strong> XSS</a></li><li class="chapter-item "><a href="../../posts/ctf/2.3_Upload File.html"><strong aria-hidden="true">19.23.</strong> Upload File</a></li><li class="chapter-item "><a href="../../posts/ctf/2.4_serialize_unserialize.html"><strong aria-hidden="true">19.24.</strong> serialize unserialize</a></li><li class="chapter-item "><a href="../../posts/ctf/2.5_Race condition.html"><strong aria-hidden="true">19.25.</strong> Race condition</a></li><li class="chapter-item "><a href="../../posts/ctf/3.2_PWN_note.html"><strong aria-hidden="true">19.26.</strong> PWN_note</a></li><li class="chapter-item "><a href="../../posts/ctf/3.3_pwn HCTF2016 brop.html"><strong aria-hidden="true">19.27.</strong> pwn HCTF2016 brop</a></li><li class="chapter-item "><a href="../../posts/ctf/pwn_patch_defense_skill.html"><strong aria-hidden="true">19.28.</strong> PWN Patch defense skill</a></li><li class="chapter-item "><a href="../../posts/ctf/pwn_stack_overflow.html"><strong aria-hidden="true">19.29.</strong> PWN stack overflow</a></li><li class="chapter-item "><a href="../../posts/ctf/pwn_heap_overflow.html"><strong aria-hidden="true">19.30.</strong> PWN heap overflow</a></li><li class="chapter-item "><a href="../../posts/ctf/pwn_format_string_vulnerability.html"><strong aria-hidden="true">19.31.</strong> PWN Format String Vulnerability</a></li><li class="chapter-item "><a href="../../posts/ctf/kali_linux_tutorials.html"><strong aria-hidden="true">19.32.</strong> Kali linux tutorials</a></li><li class="chapter-item "><a href="../../posts/ctf/google_dorks_2023_lists.html"><strong aria-hidden="true">19.33.</strong> Google Dorks 2023 Lists</a></li><li class="chapter-item "><a href="../../posts/ctf/dvwa_writeup.html"><strong aria-hidden="true">19.34.</strong> DVWA WriteUp</a></li><li class="chapter-item "><a href="../../posts/ctf/bwapp_writeup.html"><strong aria-hidden="true">19.35.</strong> bWAPP WriteUp</a></li><li class="chapter-item "><a href="../../posts/ctf/sqlilabs_writeup.html"><strong aria-hidden="true">19.36.</strong> sqlilabs WriteUp</a></li><li class="chapter-item "><a href="../../posts/ctf/ctf_train_at_hangzhou.html"><strong aria-hidden="true">19.37.</strong> ctf train at hangzhou</a></li><li class="chapter-item "><a href="../../posts/ctf/ctf_common_mindmap_list.html"><strong aria-hidden="true">19.38.</strong> ctf common mindmap list</a></li><li class="chapter-item "><a href="../../posts/ctf/error_based_sql_injection.html"><strong aria-hidden="true">19.39.</strong> Error Based SQL Injection</a></li><li class="chapter-item "><a href="../../posts/ctf/urlfinder_tutorial.html"><strong aria-hidden="true">19.40.</strong> URLFinder Tutorial</a></li><li class="chapter-item "><a href="../../posts/ctf/observer_ward_tutorial.html"><strong aria-hidden="true">19.41.</strong> observer_ward Tutorial</a></li><li class="chapter-item "><a href="../../posts/ctf/mysql_udf_.html"><strong aria-hidden="true">19.42.</strong> MySQL UDF 提权</a></li><li class="chapter-item "><a href="../../posts/ctf/nuclei__tutorial.html"><strong aria-hidden="true">19.43.</strong> Nuclei Tutorial</a></li><li class="chapter-item "><a href="../../posts/ctf/2024_ctf_solution_thinking.html"><strong aria-hidden="true">19.44.</strong> 2024 ctf solution thinking</a></li><li class="chapter-item "><a href="../../posts/ctf/man_che_si_te_bian_ma.html"><strong aria-hidden="true">19.45.</strong> 曼彻斯特编码</a></li></ol></li></ol>
|
||
</div>
|
||
<div id="sidebar-resize-handle" class="sidebar-resize-handle">
|
||
<div class="sidebar-resize-indicator"></div>
|
||
</div>
|
||
</nav>
|
||
|
||
<!-- Track and set sidebar scroll position -->
|
||
<script>
|
||
var sidebarScrollbox = document.querySelector('#sidebar .sidebar-scrollbox');
|
||
sidebarScrollbox.addEventListener('click', function(e) {
|
||
if (e.target.tagName === 'A') {
|
||
sessionStorage.setItem('sidebar-scroll', sidebarScrollbox.scrollTop);
|
||
}
|
||
}, { passive: true });
|
||
var sidebarScrollTop = sessionStorage.getItem('sidebar-scroll');
|
||
sessionStorage.removeItem('sidebar-scroll');
|
||
if (sidebarScrollTop) {
|
||
// preserve sidebar scroll position when navigating via links within sidebar
|
||
sidebarScrollbox.scrollTop = sidebarScrollTop;
|
||
} else {
|
||
// scroll sidebar to current active section when navigating via "next/previous chapter" buttons
|
||
var activeSection = document.querySelector('#sidebar .active');
|
||
if (activeSection) {
|
||
activeSection.scrollIntoView({ block: 'center' });
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<div id="page-wrapper" class="page-wrapper">
|
||
|
||
<div class="page">
|
||
<div id="menu-bar-hover-placeholder"></div>
|
||
<div id="menu-bar" class="menu-bar sticky">
|
||
<div class="left-buttons">
|
||
<label id="sidebar-toggle" class="icon-button" for="sidebar-toggle-anchor" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
|
||
<i class="fa fa-bars"></i>
|
||
</label>
|
||
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
|
||
<i class="fa fa-paint-brush"></i>
|
||
</button>
|
||
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
|
||
<li role="none"><button role="menuitem" class="theme" id="light">Light</button></li>
|
||
<li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
|
||
<li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
|
||
<li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
|
||
<li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
|
||
</ul>
|
||
<button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
|
||
<i class="fa fa-search"></i>
|
||
</button>
|
||
</div>
|
||
|
||
<h1 class="menu-title">Andrew's Blog</h1>
|
||
|
||
<div class="right-buttons">
|
||
<a href="https://gitlink.org.cn/dnrops/dnrops.gitlink.net.git" title="Git repository" aria-label="Git repository">
|
||
<i id="git-repository-button" class="fa fa-github"></i>
|
||
</a>
|
||
|
||
</div>
|
||
</div>
|
||
|
||
<div id="search-wrapper" class="hidden">
|
||
<form id="searchbar-outer" class="searchbar-outer">
|
||
<input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
|
||
</form>
|
||
<div id="searchresults-outer" class="searchresults-outer hidden">
|
||
<div id="searchresults-header" class="searchresults-header"></div>
|
||
<ul id="searchresults">
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
|
||
<script>
|
||
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
|
||
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
|
||
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
|
||
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
|
||
});
|
||
</script>
|
||
|
||
<div id="content" class="content">
|
||
<main>
|
||
<h1 id="react路由的使用"><a class="header" href="#react路由的使用">React路由的使用</a></h1>
|
||
<p>使用React路由之前,我们需要先安装 <code>react-router-dom</code>这个包。比如:</p>
|
||
<pre><code class="language-bash">yarn add react-router-dom
|
||
</code></pre>
|
||
<p>代码举例:
|
||
(1)index.html</p>
|
||
<pre><code class="language-html"><!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||
<title>Document</title>
|
||
</head>
|
||
<body>
|
||
<!-- 容器,通过 React 渲染得到的 虚拟DOM,会呈现到这个位置 -->
|
||
<div id="app"></div>
|
||
</body>
|
||
</html>
|
||
</code></pre>
|
||
<p>(2)main.js:</p>
|
||
<pre><code class="language-javascript">// JS打包入口文件
|
||
// 1. 导入包
|
||
import React from "react";
|
||
import ReactDOM from "react-dom";
|
||
import App from "./App.jsx";
|
||
// 使用 render 函数渲染 虚拟DOM
|
||
ReactDOM.render(<App />, document.getElementById("app"));
|
||
</code></pre>
|
||
<p>(3)app.jsx:</p>
|
||
<pre><code class="language-js">import React from "react";
|
||
// 如果要使用 路由模块,第一步,运行 yarn add react-router-dom
|
||
// 第二步,导入 路由模块
|
||
// HashRouter 表示一个路由的跟容器,将来,所有的路由相关的东西,都要包裹在 HashRouter 里面,而且,一个网站中,只需要使用一次 HashRouter 就好了;
|
||
// Route 表示一个路由规则, 在 Route 上,有两个比较重要的属性, path component
|
||
// Link 表示一个路由的链接 ,就好比 vue 中的 <router-link to=""></router-link>
|
||
import { HashRouter, Route, Link } from "react-router-dom";
|
||
import Home from "./components/Home.jsx";
|
||
import Movie from "./components/Movie.jsx";
|
||
import About from "./components/About.jsx";
|
||
export default class App extends React.Component {
|
||
constructor(props) {
|
||
super(props);
|
||
this.state = {};
|
||
}
|
||
render() {
|
||
// 当 使用 HashRouter 把 App 根组件的元素包裹起来之后,网站就已经启用路由了
|
||
// 在一个 HashRouter 中,只能有唯一的一个根元素
|
||
// 在一个网站中,只需要使用 唯一的一次 <HashRouter></HashRouter> 即可
|
||
return (
|
||
<HashRouter>
|
||
<div>
|
||
<h1>这是网站的APP根组件</h1>
|
||
<hr />
|
||
<Link to="/home">首页</Link>&nbsp;&nbsp;
|
||
<Link to="/movie">电影</Link>&nbsp;&nbsp;
|
||
<Link to="/about">关于</Link>
|
||
<hr />
|
||
{/* Route 创建的标签,就是路由规则,其中 path 表示要匹配的路由,component 表示要展示的组件 */}
|
||
{/* 在 vue 中有个 router-view 的路由标签,专门用来放置,匹配到的路由组件的,但是,在 react-router 中,并没有类似于这样的标签,而是 ,直接把 Route 标签,当作的 坑(占位符) */}
|
||
{/* Route 具有两种身份:1. 它是一个路由匹配规则; 2. 它是 一个占位符,表示将来匹配到的组件都放到这个位置 */}
|
||
<Route path="/home" component={Home} />
|
||
<hr />
|
||
<Route path="/movie" component={Movie} />
|
||
<hr />
|
||
<Route path="/about" component={About} />
|
||
</div>
|
||
</HashRouter>
|
||
);
|
||
}
|
||
}
|
||
</code></pre>
|
||
<p>(4)ReactDemo/src/components/Home.jsx</p>
|
||
<pre><code class="language-js">import React from "react";
|
||
export default class Home extends React.Component {
|
||
constructor(props) {
|
||
super(props);
|
||
this.state = {};
|
||
}
|
||
render() {
|
||
return <div>Home组件</div>;
|
||
}
|
||
}
|
||
</code></pre>
|
||
<p>(5)ReactDemo/src/components/Movie.jsx</p>
|
||
<pre><code class="language-js">import React from "react";
|
||
export default class Movie extends React.Component {
|
||
constructor(props) {
|
||
super(props);
|
||
this.state = {};
|
||
}
|
||
render() {
|
||
return <div>Movie组件</div>;
|
||
}
|
||
}
|
||
</code></pre>
|
||
<p>(6)ReactDemo/src/components/About.jsx</p>
|
||
<pre><code class="language-js">import React from "react";
|
||
export default class About extends React.Component {
|
||
constructor(props) {
|
||
super(props);
|
||
this.state = {};
|
||
}
|
||
render() {
|
||
return <div>About组件</div>;
|
||
}
|
||
}
|
||
</code></pre>
|
||
<p>运行结果:
|
||
20190214_1000.png</p>
|
||
<h2 id="匹配路由参数"><a class="header" href="#匹配路由参数">匹配路由参数</a></h2>
|
||
<h3 id="模糊匹配与精准匹配"><a class="header" href="#模糊匹配与精准匹配">模糊匹配与精准匹配</a></h3>
|
||
<p>我们在上面的代码中,进一步修改。假设 Movie 这个组件修改成这种路由匹配方式:</p>
|
||
<pre><code class="language-html"><Link to="/movie/top250">电影</Link>
|
||
<Route path="/movie" component={Movie} />
|
||
</code></pre>
|
||
<p>上面这种匹配方式,也是可以成功匹配到的。这是为啥呢?
|
||
这是因为:默认情况下,路由中的匹配规则,是<strong>模糊匹配</strong>的。如果 路由可以部分匹配成功,就会展示这个路由对应的组件。
|
||
如果想让路由规则,进行<strong>精确匹配</strong>,可以为Route添加 <code>exact</code> 属性。比如下面这种写法,因为是开启了精准匹配,所以是匹配不到的:(无法匹配)</p>
|
||
<pre><code class="language-html"><Link to="/movie/top250/20">电影</Link>
|
||
<Route path="/movie/" component={Movie} exact/>
|
||
</code></pre>
|
||
<p>另外,如果要匹配参数,可以在匹配规则中,使用 <code>:</code> 修饰符,表示这个位置匹配到的是参数。举例如下:(匹配正常)</p>
|
||
<pre><code class="language-html"><Link to="/movie/top250/20">电影</Link>&nbsp;&nbsp;
|
||
<Route path="/movie/:type/:id" component={Movie} exact/>
|
||
</code></pre>
|
||
<h3 id="获取路由参数"><a class="header" href="#获取路由参数">获取路由参数</a></h3>
|
||
<p>继续修改上面的代码。如果我想在 Movie 组件中显示路由中的参数,怎么做呢?
|
||
我们可以通过 <code>props.match.params</code>获取路由中的参数。举例做法如下:
|
||
app.jsx中的匹配规则如下:</p>
|
||
<pre><code class="language-html"><Link to="/movie/top100/5">电影</Link>&nbsp;&nbsp;
|
||
<Route path="/movie/:type/:id" component={Movie} exact/>
|
||
</code></pre>
|
||
<p>Moivie 组件的写法如下:</p>
|
||
<pre><code class="language-java">import React from "react";
|
||
export default class Movie extends React.Component {
|
||
constructor(props) {
|
||
super(props);
|
||
this.state = {
|
||
routeParams: props.match.params // 把路由中的参数保存到 state 中
|
||
};
|
||
}
|
||
render() {
|
||
console.log(this);
|
||
// 如果想要从路由规则中,提取匹配到的参数,进行使用,可以使用 this.props.match.params.*** 来访问
|
||
return (
|
||
<div>
|
||
{/* Movie --- {this.props.match.params.type} --- {this.props.match.params.id} */}
|
||
Movie --- {this.state.routeParams.type} --- {this.state.routeParams.id}
|
||
</div>
|
||
);
|
||
}
|
||
}
|
||
</code></pre>
|
||
<h1 id="beginners-guide-to-react-router"><a class="header" href="#beginners-guide-to-react-router">Beginner’s Guide to React Router</a></h1>
|
||
<p>React is a JavaScript library for building user interfaces. We can also extend it to build multi-page applications with the help of React Router. This is a third-party library that enables routing in our React apps.
|
||
In this tutorial, we are going to cover everything you need to know to get started with React Router.</p>
|
||
<h2 id="setting-up-the-project"><a class="header" href="#setting-up-the-project">Setting up the project</a></h2>
|
||
<p>To be able to follow along, you will need to create a new React app by running the following command in your terminal:</p>
|
||
<pre><code class="language-bash">npx create-react-app react-router-guide
|
||
</code></pre>
|
||
<p>Then, add these lines of code to the <code>App.js</code> file:</p>
|
||
<pre><code class="language-js">import React from "react";
|
||
import "./index.css"
|
||
export default function App() {
|
||
return (
|
||
<main>
|
||
<nav>
|
||
<ul>
|
||
<li><a href="/">Home</a></li>
|
||
<li><a href="/about">About</a></li>
|
||
<li><a href="/contact">Contact</a></li>
|
||
</ul>
|
||
</nav>
|
||
</main>
|
||
);
|
||
}
|
||
// Home Page
|
||
const Home = () => (
|
||
<Fragment>
|
||
<h1>Home</h1>
|
||
<FakeText />
|
||
</Fragment>
|
||
);
|
||
// About Page
|
||
const About = () => (
|
||
<Fragment>
|
||
<h1>About</h1>
|
||
<FakeText />
|
||
</Fragment>
|
||
);
|
||
// Contact Page
|
||
const Contact = () => (
|
||
<Fragment>
|
||
<h1>Contact</h1>
|
||
<FakeText />
|
||
</Fragment>
|
||
);
|
||
const FakeText = () => (
|
||
<p>
|
||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
||
</p>
|
||
)
|
||
</code></pre>
|
||
<p>Then, if you’re ready to go, let’s start by answering an important question: what is routing?</p>
|
||
<h2 id="what-is-routing"><a class="header" href="#what-is-routing">What is routing?</a></h2>
|
||
<p>Routing is the capacity to show different pages to the user. That means the user can move between different parts of an application by entering a URL or clicking on an element.
|
||
As you may already know, by default, React comes without routing. And to enable it in our project, we need to add a library named <a href="https://reacttraining.com/react-router/web/guides/quick-start">react-router</a>.
|
||
To install it, you will have to run the following command in your terminal:</p>
|
||
<pre><code class="language-bash">yarn add react-router-dom
|
||
</code></pre>
|
||
<p>Or</p>
|
||
<pre><code class="language-bash">npm install react-router-dom
|
||
</code></pre>
|
||
<p>Now, we’ve successfully installed our router, let’s start using it in the next section.</p>
|
||
<h2 id="setting-up-the-router"><a class="header" href="#setting-up-the-router">Setting up the router</a></h2>
|
||
<p>To enable routing in our React app, we first need to import <code>BrowserRouter</code> from <code>react-router-dom</code>.
|
||
In the <code>App.js</code> file, enter the following:</p>
|
||
<pre><code class="language-js">import React, { Fragment } from "react";
|
||
import "./index.css"
|
||
import { BrowserRouter as Router } from "react-router-dom";
|
||
export default function App() {
|
||
return (
|
||
<Router>
|
||
<main>
|
||
<nav>
|
||
<ul>
|
||
<li><a href="/">Home</a></li>
|
||
<li><a href="/about">About</a></li>
|
||
<li><a href="/contact">Contact</a></li>
|
||
</ul>
|
||
</nav>
|
||
</main>
|
||
</Router>
|
||
);
|
||
}
|
||
</code></pre>
|
||
<p>This should hold everything in our app where routing is needed. That means, if we need routing in our entire app, we must wrap our higher component with <code>BrowserRouter</code>.
|
||
By the way, you don’t have to rename <code>BrowserRouter as Router</code> as I do here, I just want to keep things readable.
|
||
A router alone doesn’t do much. So let’s add a route in the next section.</p>
|
||
<h2 id="rendering-routes"><a class="header" href="#rendering-routes">Rendering routes</a></h2>
|
||
<p>To render routes, we have to import the <code>Route</code> component from the router package.
|
||
In your <code>App.js</code> file, add the following code:</p>
|
||
<pre><code class="language-js">import React, { Fragment } from "react";
|
||
import "./index.css"
|
||
import { BrowserRouter as Router, Route } from "react-router-dom";
|
||
export default function App() {
|
||
return (
|
||
<Router>
|
||
<main>
|
||
<nav>
|
||
<ul>
|
||
<li><a href="/">Home</a></li>
|
||
<li><a href="/about">About</a></li>
|
||
<li><a href="/contact">Contact</a></li>
|
||
</ul>
|
||
</nav>
|
||
<Route path="/" render={() => <h1>Welcome!</h1>} />
|
||
</main>
|
||
</Router>
|
||
);
|
||
}
|
||
</code></pre>
|
||
<p>Then, add it where we want to render the content. The <code>Route</code> component has several properties. But here, we just need <code>path</code> and <code>render</code>.
|
||
<code>path</code>: the path of the route. Here, we use <code>/</code> to define the path of the home page.
|
||
<code>render</code>: will display the content whenever the route is reached. Here, we’ll render a welcome message to the user.
|
||
In some cases serving routes like that is perfectly fine. But imagine a case when we have to deal with a real component – using <code>render</code> may not be the right solution.
|
||
So, how can we display a real component? Well, the <code>Route</code> component has another property named <code>component</code>.
|
||
Let’s update our example a bit to see it in action.
|
||
In your <code>App.js</code> file, add the following code:</p>
|
||
<pre><code class="language-js">import React, { Fragment } from "react";
|
||
import "./index.css"
|
||
import { BrowserRouter as Router, Route } from "react-router-dom";
|
||
export default function App() {
|
||
return (
|
||
<Router>
|
||
<main>
|
||
<nav>
|
||
<ul>
|
||
<li><a href="/">Home</a></li>
|
||
<li><a href="/about">About</a></li>
|
||
<li><a href="/contact">Contact</a></li>
|
||
</ul>
|
||
</nav>
|
||
<Route path="/" component={Home} />
|
||
</main>
|
||
</Router>
|
||
);
|
||
}
|
||
const Home = () => (
|
||
<Fragment>
|
||
<h1>Home</h1>
|
||
<FakeText />
|
||
</Fragment>
|
||
);
|
||
</code></pre>
|
||
<p>Now, instead of rendering a message, our route will load the <code>Home</code> component.
|
||
To get the full power of React Router, we need to have multiple pages and links to play with. We already have pages (components if you want, too), so now let’s add some links so we can switch between pages.</p>
|
||
<h2 id="using-links-to-switch-pages"><a class="header" href="#using-links-to-switch-pages">Using links to switch pages</a></h2>
|
||
<p>To add links to our project, we will use the React Router again.
|
||
In your <code>App.js</code> file, add the following code:</p>
|
||
<pre><code class="language-js">import React, { Fragment } from "react";
|
||
import "./index.css"
|
||
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
|
||
export default function App() {
|
||
return (
|
||
<Router>
|
||
<main>
|
||
<nav>
|
||
<ul>
|
||
<li><Link to="/">Home</Link></li>
|
||
<li><Link to="/about">About</Link></li>
|
||
<li><Link to="/contact">Contact</Link></li>
|
||
</ul>
|
||
</nav>
|
||
<Route path="/" exact component={Home} />
|
||
<Route path="/about" component={About} />
|
||
<Route path="/contact" component={Contact} />
|
||
</main>
|
||
</Router>
|
||
);
|
||
}
|
||
const Home = () => (
|
||
<Fragment>
|
||
<h1>Home</h1>
|
||
<FakeText />
|
||
</Fragment>
|
||
);
|
||
const About = () => (
|
||
<Fragment>
|
||
<h1>About</h1>
|
||
<FakeText />
|
||
</Fragment>
|
||
);
|
||
const Contact = () => (
|
||
<Fragment>
|
||
<h1>Contact</h1>
|
||
<FakeText />
|
||
</Fragment>
|
||
);
|
||
</code></pre>
|
||
<p>After importing <code>Link</code>, we have to update our navigation bar a bit. Now, instead of using <code>a</code> tag and <code>href</code>, React Router uses <code>Link</code> and <code>to</code> to, well, be able to switch between pages without reloading it.
|
||
Then, we need to add two new routes, <code>About</code> and <code>Contact</code>, to be able to switch between pages or components.
|
||
Now, we can go to different parts of our app through links. But there is an issue with our router: the <code>Home</code> component is always displayed even if we switch to other pages.
|
||
This is because React Router will check if the <code>path</code> defined starts with <code>/</code>. If that’s the case, it will render the component. And here, our first route starts with <code>/</code>, so the <code>Home</code> component will be rendered each time.
|
||
However, we can still change the default behavior by adding the <code>exact</code> property to <code>Route</code>.
|
||
In <code>App.js</code>, add:</p>
|
||
<pre><code class="language-js"><Route path="/" exact component={Home} />
|
||
</code></pre>
|
||
<p>By updating the <code>Home</code> route with <code>exact</code>, now it will be rendered only if it matches the full path.
|
||
We can still enhance it by wrapping our routes with <code>Switch</code> to tell to React Router to load only one route at a time.
|
||
In <code>App.js</code>, add:</p>
|
||
<pre><code class="language-js">import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom";
|
||
<Switch>
|
||
<Route path="/" exact component={Home} />
|
||
<Route path="/about" component={About} />
|
||
<Route path="/contact" component={Contact} />
|
||
</Switch>
|
||
</code></pre>
|
||
<p>Now that we have new links, let’s use them to pass parameters.</p>
|
||
<h2 id="passing-route-parameters"><a class="header" href="#passing-route-parameters">Passing route parameters</a></h2>
|
||
<p>To pass data between pages, we have to update our example.
|
||
In your <code>App.js</code> file, add the following code:</p>
|
||
<pre><code class="language-js">import React, { Fragment } from "react";
|
||
import "./index.css"
|
||
import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom";
|
||
export default function App() {
|
||
const name = 'John Doe'
|
||
return (
|
||
<Router>
|
||
<main>
|
||
<nav>
|
||
<ul>
|
||
<li><Link to="/">Home</Link></li>
|
||
<li><Link to={`/about/${name}`}>About</Link></li>
|
||
<li><Link to="/contact">Contact</Link></li>
|
||
</ul>
|
||
</nav>
|
||
<Switch>
|
||
<Route path="/" exact component={Home} />
|
||
<Route path="/about/:name" component={About} />
|
||
<Route path="/contact" component={Contact} />
|
||
</Switch>
|
||
</main>
|
||
</Router>
|
||
);
|
||
}
|
||
const Home = () => (
|
||
<Fragment>
|
||
<h1>Home</h1>
|
||
<FakeText />
|
||
</Fragment>
|
||
);
|
||
const About = ({match:{params:{name}}}) => (
|
||
// props.match.params.name
|
||
<Fragment>
|
||
<h1>About {name}</h1>
|
||
<FakeText />
|
||
</Fragment>
|
||
);
|
||
const Contact = () => (
|
||
<Fragment>
|
||
<h1>Contact</h1>
|
||
<FakeText />
|
||
</Fragment>
|
||
);
|
||
</code></pre>
|
||
<p>As you can see here, we start by declaring a new constant <code>name</code> which will be passed as a parameter to the <code>About</code> page. And we append <code>name</code> to the corresponding link.
|
||
With that, we now have to update the <code>About</code> route by adjusting its path to receive <code>name</code> as a parameter <code>path="/about/:name"</code>.
|
||
Now, the parameter will be received as props from the <code>About</code> component. The only thing we have to do now is destructure the props and get back the <code>name</code> property. By the way, <code>{match:{params:{name}}}</code> is the same as <code>props.match.params.name</code>.
|
||
We’ve done a lot up to this point. But in some cases we don’t want to use links to navigate between pages.
|
||
Sometimes, we have to wait for an operation to finish before navigating to the next page.
|
||
So, let’s handle that case in the next section.</p>
|
||
<h2 id="navigating-programmatically"><a class="header" href="#navigating-programmatically">Navigating programmatically</a></h2>
|
||
<p>The props we receive have some convenient methods we can use to navigate between pages.
|
||
In <code>App.js</code>, add:</p>
|
||
<pre><code class="language-js">const Contact = ({history}) => (
|
||
<Fragment>
|
||
<h1>Contact</h1>
|
||
<button onClick={() => history.push('/') } >Go to home</button>
|
||
<FakeText />
|
||
</Fragment>
|
||
);
|
||
</code></pre>
|
||
<p>Here, we pull the <code>history</code> object from the props we receive. It has some handy methods like <code>goBack</code>, <code>goForward</code>, and so on. But here, we will use the <code>push</code> method to be able to go to the Home page.
|
||
Now, let’s handle the case when we want to redirect our user after an action.</p>
|
||
<h2 id="redirecting-to-another-page"><a class="header" href="#redirecting-to-another-page">Redirecting to another page</a></h2>
|
||
<p>The React Router has another component named <code>Redirect</code>. As you guessed, it helps us redirect the user to another page
|
||
In <code>App.js</code>, add:</p>
|
||
<pre><code class="language-js">import { BrowserRouter as Router, Route, Link, Switch, Redirect } from "react-router-dom";
|
||
const About = ({match:{params:{name}}}) => (
|
||
// props.match.params.name
|
||
<Fragment>
|
||
{ name !== 'John Doe' ? <Redirect to="/" /> : null }
|
||
<h1>About {name}</h1>
|
||
<FakeText />
|
||
</Fragment>
|
||
);
|
||
</code></pre>
|
||
<p>Now, if the <code>name</code> passed as a parameter is not equal to <code>John Doe</code>, the user will be redirected to the home page.
|
||
You could argue that you should redirect the user with <code>props.history.push('/)</code>. Well, the <code>Redirect</code> component replaces the page and therefore the user can’t go back to the previous page. But, with the push method they can. However, you can use <code>props.history.replace('/)</code> to mimic the <code>Redirect</code> behavior.
|
||
Now let’s move on and handle the case when the user hits a route that doesn’t exist.</p>
|
||
<h2 id="redirecting-to-a-404-page"><a class="header" href="#redirecting-to-a-404-page">Redirecting to a 404 page</a></h2>
|
||
<p>To redirect the user to a 404 page, you can create a component to show it. But here, to keep things simple, I will just display a message with <code>render</code>.</p>
|
||
<pre><code class="language-js">import React, { Fragment } from "react";
|
||
import "./index.css"
|
||
import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom";
|
||
export default function App() {
|
||
const name = 'John Doe'
|
||
return (
|
||
<Router>
|
||
<main>
|
||
<nav>
|
||
<ul>
|
||
<li><Link to="/">Home</Link></li>
|
||
<li><Link to={`/about/${name}`}>About</Link></li>
|
||
<li><Link to="/contact">Contact</Link></li>
|
||
</ul>
|
||
</nav>
|
||
<Switch>
|
||
<Route path="/" exact component={Home} />
|
||
<Route path="/about/:name" component={About} />
|
||
<Route path="/contact" component={Contact} />
|
||
<Route render={() => <h1>404: page not found</h1>} />
|
||
</Switch>
|
||
</main>
|
||
</Router>
|
||
);
|
||
}
|
||
</code></pre>
|
||
<p>The new route we’ve added will catch every path that doesn’t exist and redirect the user to the 404 page.
|
||
Now, let’s move on and learn how to protect our routes in the next section.</p>
|
||
<h2 id="guarding-routes"><a class="header" href="#guarding-routes">Guarding routes</a></h2>
|
||
<p>There are many ways to protect routes to React. But here I will just check if the user is authenticated and redirect them to the appropriate page.</p>
|
||
<pre><code class="language-js">import React, { Fragment } from "react";
|
||
import "./index.css"
|
||
import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom";
|
||
export default function App() {
|
||
const name = 'John Doe'
|
||
const isAuthenticated = false
|
||
return (
|
||
<Router>
|
||
<main>
|
||
<nav>
|
||
<ul>
|
||
<li><Link to="/">Home</Link></li>
|
||
<li><Link to={`/about/${name}`}>About</Link></li>
|
||
<li><Link to="/contact">Contact</Link></li>
|
||
</ul>
|
||
</nav>
|
||
<Switch>
|
||
<Route path="/" exact component={Home} />
|
||
{
|
||
isAuthenticated ?
|
||
<>
|
||
<Route path="/about/:name" component={About} />
|
||
<Route path="/contact" component={Contact} />
|
||
</> : <Redirect to="/" />
|
||
}
|
||
</Switch>
|
||
</main>
|
||
</Router>
|
||
);
|
||
}
|
||
</code></pre>
|
||
<p>As you can see here, I declared a variable to mimic authentication. Then, check if the user is authenticated or not. If they are, render protected pages. Otherwise redirect them to the home page.
|
||
We’ve covered a lot up to this point, but an interesting part remains: router hooks.
|
||
Let’s move to the final section and introduce Hooks.</p>
|
||
<h2 id="router-hooks"><a class="header" href="#router-hooks">Router Hooks</a></h2>
|
||
<p>Router hooks make things much easier. Now you can access the history, location, or parameters in an easy and elegant way.</p>
|
||
<h3 id="usehistory"><a class="header" href="#usehistory">useHistory</a></h3>
|
||
<p>The <code>useHistory</code> hook gives us access to the history instance without pulling it from props.</p>
|
||
<pre><code class="language-js">import { useHistory } from "react-router-dom";
|
||
const Contact = () => {
|
||
const history = useHistory();
|
||
return (
|
||
<Fragment>
|
||
<h1>Contact</h1>
|
||
<button onClick={() => history.push('/') } >Go to home</button>
|
||
</Fragment>
|
||
)
|
||
};
|
||
</code></pre>
|
||
<h3 id="useparams"><a class="header" href="#useparams">useParams</a></h3>
|
||
<p>This hook helps us get the parameter passed on the URL without using the props object.</p>
|
||
<pre><code class="language-js">import { BrowserRouter as Router, Route, Link, Switch, useParams } from "react-router-dom";
|
||
export default function App() {
|
||
const name = 'John Doe'
|
||
return (
|
||
<Router>
|
||
<main>
|
||
<nav>
|
||
<ul>
|
||
<li><Link to="/">Home</Link></li>
|
||
<li><Link to={`/about/${name}`}>About</Link></li>
|
||
</ul>
|
||
</nav>
|
||
<Switch>
|
||
<Route path="/" exact component={Home} />
|
||
<Route path="/about/:name" component={About} />
|
||
</Switch>
|
||
</main>
|
||
</Router>
|
||
);
|
||
}
|
||
const About = () => {
|
||
const { name } = useParams()
|
||
return (
|
||
// props.match.params.name
|
||
<Fragment>
|
||
{ name !== 'John Doe' ? <Redirect to="/" /> : null }
|
||
<h1>About {name}</h1>
|
||
<Route component={Contact} />
|
||
</Fragment>
|
||
)
|
||
};
|
||
</code></pre>
|
||
<h3 id="uselocation"><a class="header" href="#uselocation">useLocation</a></h3>
|
||
<p>This hook returns the location object that represents the current URL.</p>
|
||
<pre><code class="language-js">import { useLocation } from "react-router-dom";
|
||
const Contact = () => {
|
||
const { pathname } = useLocation();
|
||
return (
|
||
<Fragment>
|
||
<h1>Contact</h1>
|
||
<p>Current URL: {pathname}</p>
|
||
</Fragment>
|
||
)
|
||
};
|
||
</code></pre>
|
||
<h2 id="final-thoughts"><a class="header" href="#final-thoughts">Final Thoughts</a></h2>
|
||
<p>React Router is an amazing library that helps us go from a single page to a multi-page application feeling with great usability. (Just keep in mind – at the end of the day, it’s still a single page app).
|
||
And now with router hooks, you can see how easy and elegant they are. They’re definitely something to consider in your next project.</p>
|
||
|
||
</main>
|
||
|
||
<nav class="nav-wrapper" aria-label="Page navigation">
|
||
<!-- Mobile navigation buttons -->
|
||
<a rel="prev" href="../../posts/react/react_life_cycle.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
||
<i class="fa fa-angle-left"></i>
|
||
</a>
|
||
|
||
<a rel="next prefetch" href="../../posts/react/react_this.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
||
<i class="fa fa-angle-right"></i>
|
||
</a>
|
||
|
||
<div style="clear: both"></div>
|
||
</nav>
|
||
</div>
|
||
</div>
|
||
|
||
<nav class="nav-wide-wrapper" aria-label="Page navigation">
|
||
<a rel="prev" href="../../posts/react/react_life_cycle.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
||
<i class="fa fa-angle-left"></i>
|
||
</a>
|
||
|
||
<a rel="next prefetch" href="../../posts/react/react_this.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
||
<i class="fa fa-angle-right"></i>
|
||
</a>
|
||
</nav>
|
||
|
||
</div>
|
||
|
||
|
||
|
||
<script>
|
||
window.playground_line_numbers = true;
|
||
</script>
|
||
|
||
<script>
|
||
window.playground_copyable = true;
|
||
</script>
|
||
|
||
<script src="../../ace.js"></script>
|
||
<script src="../../editor.js"></script>
|
||
<script src="../../mode-rust.js"></script>
|
||
<script src="../../theme-dawn.js"></script>
|
||
<script src="../../theme-tomorrow_night.js"></script>
|
||
|
||
<script src="../../elasticlunr.min.js"></script>
|
||
<script src="../../mark.min.js"></script>
|
||
<script src="../../searcher.js"></script>
|
||
|
||
<script src="../../clipboard.min.js"></script>
|
||
<script src="../../highlight.js"></script>
|
||
<script src="../../book.js"></script>
|
||
|
||
<!-- Custom JS scripts -->
|
||
<script src="../../src/js/custom.js"></script>
|
||
|
||
|
||
</div>
|
||
</body>
|
||
</html>
|