Преглед на файлове

Redux: Redux状态注入项目

大侠 преди 2 години
родител
ревизия
bde2e95329
променени са 37 файла, в които са добавени 459 реда и са изтрити 494 реда
  1. 0 0
      15_React/day-6/code/case/.gitignore
  2. 20 0
      15_React/day-6/code/case/counter.jsx
  3. 3 5
      15_React/day-6/code/case/counter.module.css
  4. 23 0
      15_React/day-6/code/learn-redux/.gitignore
  5. 26 2
      15_React/day-6/code/learn-redux/README.md
  6. 265 199
      15_React/day-6/code/learn-redux/package-lock.json
  7. 3 2
      15_React/day-6/code/learn-redux/package.json
  8. BIN
      15_React/day-6/code/learn-redux/public/favicon.ico
  9. 1 1
      15_React/day-6/code/learn-redux/public/index.html
  10. BIN
      15_React/day-6/code/learn-redux/public/logo192.png
  11. BIN
      15_React/day-6/code/learn-redux/public/logo512.png
  12. 0 0
      15_React/day-6/code/learn-redux/public/manifest.json
  13. 1 0
      15_React/day-6/code/learn-redux/public/robots.txt
  14. 9 10
      15_React/day-6/code/learn-redux/src/App.css
  15. 14 0
      15_React/day-6/code/learn-redux/src/Layout/index.css
  16. 24 0
      15_React/day-6/code/learn-redux/src/Layout/index.jsx
  17. 0 0
      15_React/day-6/code/learn-redux/src/index.css
  18. 8 9
      15_React/day-6/code/learn-redux/src/index.js
  19. 0 0
      15_React/day-6/code/learn-redux/src/logo.svg
  20. 7 0
      15_React/day-6/code/learn-redux/src/pages/Counter.jsx
  21. 7 0
      15_React/day-6/code/learn-redux/src/pages/Home.jsx
  22. 0 0
      15_React/day-6/code/learn-redux/src/reportWebVitals.js
  23. 32 0
      15_React/day-6/code/learn-redux/src/router/index.js
  24. 16 0
      15_React/day-6/code/learn-redux/src/store/index.js
  25. BIN
      15_React/day-6/code/my-app/public/favicon.ico
  26. BIN
      15_React/day-6/code/my-app/public/logo192.png
  27. BIN
      15_React/day-6/code/my-app/public/logo512.png
  28. 0 58
      15_React/day-6/code/my-app/src/App.js
  29. 0 15
      15_React/day-6/code/my-app/src/App.test.js
  30. 0 8
      15_React/day-6/code/my-app/src/app/store.js
  31. 0 67
      15_React/day-6/code/my-app/src/features/counter/Counter.js
  32. 0 6
      15_React/day-6/code/my-app/src/features/counter/counterAPI.js
  33. 0 73
      15_React/day-6/code/my-app/src/features/counter/counterSlice.js
  34. 0 33
      15_React/day-6/code/my-app/src/features/counter/counterSlice.spec.js
  35. 0 1
      15_React/day-6/code/my-app/src/logo.svg
  36. 0 5
      15_React/day-6/code/my-app/src/setupTests.js
  37. BIN
      15_React/day-6/note/ReduxAsyncDataFlowDiagram-d97ff38a0f4da0f327163170ccc13e80.gif

+ 0 - 0
15_React/day-6/code/my-app/.gitignore → 15_React/day-6/code/case/.gitignore


+ 20 - 0
15_React/day-6/code/case/counter.jsx

@@ -0,0 +1,20 @@
+import styles from './counter.module.css';
+
+function Counter() {
+  return (
+    <div>
+      <h3>计数器</h3>
+      <div className={styles.row}>
+        <button className={styles.button}>-</button>
+        <span className={styles.value}></span>
+        <button className={styles.button}>+</button>
+      </div>
+      <div className={styles.row}>
+        <input className={styles.textbox} />
+        <button className={styles.button}>Add Amount</button>
+        <button className={styles.asyncButton}>Add Async</button>
+      </div>
+    </div>
+  );
+}
+export default Counter;

+ 3 - 5
15_React/day-6/code/my-app/src/features/counter/Counter.module.css → 15_React/day-6/code/case/counter.module.css

@@ -4,10 +4,6 @@
   justify-content: center;
 }
 
-.row > button {
-  margin-left: 4px;
-  margin-right: 8px;
-}
 .row:not(:last-child) {
   margin-bottom: 16px;
 }
@@ -22,6 +18,7 @@
 
 .button {
   appearance: none;
+  border: none;
   background: none;
   font-size: 32px;
   padding-left: 12px;
@@ -41,7 +38,7 @@
   padding: 2px;
   width: 64px;
   text-align: center;
-  margin-right: 4px;
+  margin-right: 8px;
 }
 
 .button:hover,
@@ -56,6 +53,7 @@
 .asyncButton {
   composes: button;
   position: relative;
+  margin-left: 8px;
 }
 
 .asyncButton:after {

+ 23 - 0
15_React/day-6/code/learn-redux/.gitignore

@@ -0,0 +1,23 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+# dependencies
+/node_modules
+/.pnp
+.pnp.js
+
+# testing
+/coverage
+
+# production
+/build
+
+# misc
+.DS_Store
+.env.local
+.env.development.local
+.env.test.local
+.env.production.local
+
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*

+ 26 - 2
15_React/day-6/code/my-app/README.md → 15_React/day-6/code/learn-redux/README.md

@@ -1,6 +1,6 @@
-# Getting Started with Create React App and Redux
+# Getting Started with Create React App
 
-This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app), using the [Redux](https://redux.js.org/) and [Redux Toolkit](https://redux-toolkit.js.org/) template.
+This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
 
 ## Available Scripts
 
@@ -44,3 +44,27 @@ You don't have to ever use `eject`. The curated feature set is suitable for smal
 You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
 
 To learn React, check out the [React documentation](https://reactjs.org/).
+
+### Code Splitting
+
+This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting)
+
+### Analyzing the Bundle Size
+
+This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size)
+
+### Making a Progressive Web App
+
+This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app)
+
+### Advanced Configuration
+
+This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration)
+
+### Deployment
+
+This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment)
+
+### `npm run build` fails to minify
+
+This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify)

+ 265 - 199
15_React/day-6/code/my-app/package-lock.json → 15_React/day-6/code/learn-redux/package-lock.json

@@ -1,20 +1,21 @@
 {
-  "name": "my-app",
+  "name": "learn-redux",
   "version": "0.1.0",
   "lockfileVersion": 2,
   "requires": true,
   "packages": {
     "": {
-      "name": "my-app",
+      "name": "learn-redux",
       "version": "0.1.0",
       "dependencies": {
         "@reduxjs/toolkit": "^1.9.2",
         "@testing-library/jest-dom": "^5.16.5",
         "@testing-library/react": "^13.4.0",
-        "@testing-library/user-event": "^14.4.3",
+        "@testing-library/user-event": "^13.5.0",
         "react": "^18.2.0",
         "react-dom": "^18.2.0",
         "react-redux": "^8.0.5",
+        "react-router-dom": "^6.8.1",
         "react-scripts": "5.0.1",
         "web-vitals": "^2.1.4"
       }
@@ -2420,20 +2421,20 @@
       }
     },
     "node_modules/@jest/expect-utils": {
-      "version": "29.4.2",
-      "resolved": "https://registry.npmmirror.com/@jest/expect-utils/-/expect-utils-29.4.2.tgz",
-      "integrity": "sha512-Dd3ilDJpBnqa0GiPN7QrudVs0cczMMHtehSo2CSTjm3zdHx0RcpmhFNVEltuEFeqfLIyWKFI224FsMSQ/nsJQA==",
+      "version": "29.4.3",
+      "resolved": "https://registry.npmmirror.com/@jest/expect-utils/-/expect-utils-29.4.3.tgz",
+      "integrity": "sha512-/6JWbkxHOP8EoS8jeeTd9dTfc9Uawi+43oLKHfp6zzux3U2hqOOVnV3ai4RpDYHOccL6g+5nrxpoc8DmJxtXVQ==",
       "dependencies": {
-        "jest-get-type": "^29.4.2"
+        "jest-get-type": "^29.4.3"
       },
       "engines": {
         "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
       }
     },
     "node_modules/@jest/expect-utils/node_modules/jest-get-type": {
-      "version": "29.4.2",
-      "resolved": "https://registry.npmmirror.com/jest-get-type/-/jest-get-type-29.4.2.tgz",
-      "integrity": "sha512-vERN30V5i2N6lqlFu4ljdTqQAgrkTFMC9xaIIfOPYBw04pufjXRty5RuXBiB1d72tGbURa/UgoiHB90ruOSivg==",
+      "version": "29.4.3",
+      "resolved": "https://registry.npmmirror.com/jest-get-type/-/jest-get-type-29.4.3.tgz",
+      "integrity": "sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==",
       "engines": {
         "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
       }
@@ -3001,6 +3002,14 @@
         }
       }
     },
+    "node_modules/@remix-run/router": {
+      "version": "1.3.2",
+      "resolved": "https://registry.npmmirror.com/@remix-run/router/-/router-1.3.2.tgz",
+      "integrity": "sha512-t54ONhl/h75X94SWsHGQ4G/ZrCEguKSRQr7DrjTciJXW0YU1QhlwYeycvK5JgkzlxmvrK7wq1NB/PLtHxoiDcA==",
+      "engines": {
+        "node": ">=14"
+      }
+    },
     "node_modules/@rollup/plugin-babel": {
       "version": "5.3.1",
       "resolved": "https://registry.npmmirror.com/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz",
@@ -3436,11 +3445,14 @@
       }
     },
     "node_modules/@testing-library/user-event": {
-      "version": "14.4.3",
-      "resolved": "https://registry.npmmirror.com/@testing-library/user-event/-/user-event-14.4.3.tgz",
-      "integrity": "sha512-kCUc5MEwaEMakkO5x7aoD+DLi02ehmEM2QCGWvNqAS1dV/fAvORWEjnjsEIvml59M7Y5kCkWN6fCCyPOe8OL6Q==",
+      "version": "13.5.0",
+      "resolved": "https://registry.npmmirror.com/@testing-library/user-event/-/user-event-13.5.0.tgz",
+      "integrity": "sha512-5Kwtbo3Y/NowpkbRuSepbyMFkZmHgD+vPzYB/RJ4oxt5Gj/avFFBYjhw27cqSVPVw/3a67NK1PbiIr9k4Gwmdg==",
+      "dependencies": {
+        "@babel/runtime": "^7.12.5"
+      },
       "engines": {
-        "node": ">=12",
+        "node": ">=10",
         "npm": ">=6"
       },
       "peerDependencies": {
@@ -3540,9 +3552,9 @@
       }
     },
     "node_modules/@types/eslint": {
-      "version": "8.21.0",
-      "resolved": "https://registry.npmmirror.com/@types/eslint/-/eslint-8.21.0.tgz",
-      "integrity": "sha512-35EhHNOXgxnUgh4XCJsGhE7zdlDhYDN/aMG6UbkByCFFNgQ7b3U+uVoqBpicFydR8JEfgdjCF7SJ7MiJfzuiTA==",
+      "version": "8.21.1",
+      "resolved": "https://registry.npmmirror.com/@types/eslint/-/eslint-8.21.1.tgz",
+      "integrity": "sha512-rc9K8ZpVjNcLs8Fp0dkozd5Pt2Apk1glO4Vgz8ix1u6yFByxfqo5Yavpy65o+93TAe24jr7v+eSBtFLvOQtCRQ==",
       "dependencies": {
         "@types/estree": "*",
         "@types/json-schema": "*"
@@ -3644,9 +3656,9 @@
       }
     },
     "node_modules/@types/jest/node_modules/@jest/schemas": {
-      "version": "29.4.2",
-      "resolved": "https://registry.npmmirror.com/@jest/schemas/-/schemas-29.4.2.tgz",
-      "integrity": "sha512-ZrGzGfh31NtdVH8tn0mgJw4khQuNHiKqdzJAFbCaERbyCP9tHlxWuL/mnMu8P7e/+k4puWjI1NOzi/sFsjce/g==",
+      "version": "29.4.3",
+      "resolved": "https://registry.npmmirror.com/@jest/schemas/-/schemas-29.4.3.tgz",
+      "integrity": "sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg==",
       "dependencies": {
         "@sinclair/typebox": "^0.25.16"
       },
@@ -3655,11 +3667,11 @@
       }
     },
     "node_modules/@types/jest/node_modules/@jest/types": {
-      "version": "29.4.2",
-      "resolved": "https://registry.npmmirror.com/@jest/types/-/types-29.4.2.tgz",
-      "integrity": "sha512-CKlngyGP0fwlgC1BRUtPZSiWLBhyS9dKwKmyGxk8Z6M82LBEGB2aLQSg+U1MyLsU+M7UjnlLllBM2BLWKVm/Uw==",
+      "version": "29.4.3",
+      "resolved": "https://registry.npmmirror.com/@jest/types/-/types-29.4.3.tgz",
+      "integrity": "sha512-bPYfw8V65v17m2Od1cv44FH+SiKW7w2Xu7trhcdTLUmSv85rfKsP+qXSjO4KGJr4dtPSzl/gvslZBXctf1qGEA==",
       "dependencies": {
-        "@jest/schemas": "^29.4.2",
+        "@jest/schemas": "^29.4.3",
         "@types/istanbul-lib-coverage": "^2.0.0",
         "@types/istanbul-reports": "^3.0.0",
         "@types/node": "*",
@@ -3671,9 +3683,9 @@
       }
     },
     "node_modules/@types/jest/node_modules/@sinclair/typebox": {
-      "version": "0.25.21",
-      "resolved": "https://registry.npmmirror.com/@sinclair/typebox/-/typebox-0.25.21.tgz",
-      "integrity": "sha512-gFukHN4t8K4+wVC+ECqeqwzBDeFeTzBXroBTqE6vcWrQGbEUpHO7LYdG0f4xnvYq4VOEwITSlHlp0JBAIFMS/g=="
+      "version": "0.25.22",
+      "resolved": "https://registry.npmmirror.com/@sinclair/typebox/-/typebox-0.25.22.tgz",
+      "integrity": "sha512-6U6r2L7rnM7EG8G1tWzIjdB3QlsHF4slgcqXNN/SF0xJOAr0nDmT2GedlkyO3mrv8mDTJ24UuOMWR3diBrCvQQ=="
     },
     "node_modules/@types/jest/node_modules/@types/yargs": {
       "version": "17.0.22",
@@ -3723,23 +3735,23 @@
       "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
     },
     "node_modules/@types/jest/node_modules/diff-sequences": {
-      "version": "29.4.2",
-      "resolved": "https://registry.npmmirror.com/diff-sequences/-/diff-sequences-29.4.2.tgz",
-      "integrity": "sha512-R6P0Y6PrsH3n4hUXxL3nns0rbRk6Q33js3ygJBeEpbzLzgcNuJ61+u0RXasFpTKISw99TxUzFnumSnRLsjhLaw==",
+      "version": "29.4.3",
+      "resolved": "https://registry.npmmirror.com/diff-sequences/-/diff-sequences-29.4.3.tgz",
+      "integrity": "sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA==",
       "engines": {
         "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
       }
     },
     "node_modules/@types/jest/node_modules/expect": {
-      "version": "29.4.2",
-      "resolved": "https://registry.npmmirror.com/expect/-/expect-29.4.2.tgz",
-      "integrity": "sha512-+JHYg9O3hd3RlICG90OPVjRkPBoiUH7PxvDVMnRiaq1g6JUgZStX514erMl0v2Dc5SkfVbm7ztqbd6qHHPn+mQ==",
+      "version": "29.4.3",
+      "resolved": "https://registry.npmmirror.com/expect/-/expect-29.4.3.tgz",
+      "integrity": "sha512-uC05+Q7eXECFpgDrHdXA4k2rpMyStAYPItEDLyQDo5Ta7fVkJnNA/4zh/OIVkVVNZ1oOK1PipQoyNjuZ6sz6Dg==",
       "dependencies": {
-        "@jest/expect-utils": "^29.4.2",
-        "jest-get-type": "^29.4.2",
-        "jest-matcher-utils": "^29.4.2",
-        "jest-message-util": "^29.4.2",
-        "jest-util": "^29.4.2"
+        "@jest/expect-utils": "^29.4.3",
+        "jest-get-type": "^29.4.3",
+        "jest-matcher-utils": "^29.4.3",
+        "jest-message-util": "^29.4.3",
+        "jest-util": "^29.4.3"
       },
       "engines": {
         "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
@@ -3754,53 +3766,53 @@
       }
     },
     "node_modules/@types/jest/node_modules/jest-diff": {
-      "version": "29.4.2",
-      "resolved": "https://registry.npmmirror.com/jest-diff/-/jest-diff-29.4.2.tgz",
-      "integrity": "sha512-EK8DSajVtnjx9sa1BkjZq3mqChm2Cd8rIzdXkQMA8e0wuXq53ypz6s5o5V8HRZkoEt2ywJ3eeNWFKWeYr8HK4g==",
+      "version": "29.4.3",
+      "resolved": "https://registry.npmmirror.com/jest-diff/-/jest-diff-29.4.3.tgz",
+      "integrity": "sha512-YB+ocenx7FZ3T5O9lMVMeLYV4265socJKtkwgk/6YUz/VsEzYDkiMuMhWzZmxm3wDRQvayJu/PjkjjSkjoHsCA==",
       "dependencies": {
         "chalk": "^4.0.0",
-        "diff-sequences": "^29.4.2",
-        "jest-get-type": "^29.4.2",
-        "pretty-format": "^29.4.2"
+        "diff-sequences": "^29.4.3",
+        "jest-get-type": "^29.4.3",
+        "pretty-format": "^29.4.3"
       },
       "engines": {
         "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
       }
     },
     "node_modules/@types/jest/node_modules/jest-get-type": {
-      "version": "29.4.2",
-      "resolved": "https://registry.npmmirror.com/jest-get-type/-/jest-get-type-29.4.2.tgz",
-      "integrity": "sha512-vERN30V5i2N6lqlFu4ljdTqQAgrkTFMC9xaIIfOPYBw04pufjXRty5RuXBiB1d72tGbURa/UgoiHB90ruOSivg==",
+      "version": "29.4.3",
+      "resolved": "https://registry.npmmirror.com/jest-get-type/-/jest-get-type-29.4.3.tgz",
+      "integrity": "sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==",
       "engines": {
         "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
       }
     },
     "node_modules/@types/jest/node_modules/jest-matcher-utils": {
-      "version": "29.4.2",
-      "resolved": "https://registry.npmmirror.com/jest-matcher-utils/-/jest-matcher-utils-29.4.2.tgz",
-      "integrity": "sha512-EZaAQy2je6Uqkrm6frnxBIdaWtSYFoR8SVb2sNLAtldswlR/29JAgx+hy67llT3+hXBaLB0zAm5UfeqerioZyg==",
+      "version": "29.4.3",
+      "resolved": "https://registry.npmmirror.com/jest-matcher-utils/-/jest-matcher-utils-29.4.3.tgz",
+      "integrity": "sha512-TTciiXEONycZ03h6R6pYiZlSkvYgT0l8aa49z/DLSGYjex4orMUcafuLXYyyEDWB1RKglq00jzwY00Ei7yFNVg==",
       "dependencies": {
         "chalk": "^4.0.0",
-        "jest-diff": "^29.4.2",
-        "jest-get-type": "^29.4.2",
-        "pretty-format": "^29.4.2"
+        "jest-diff": "^29.4.3",
+        "jest-get-type": "^29.4.3",
+        "pretty-format": "^29.4.3"
       },
       "engines": {
         "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
       }
     },
     "node_modules/@types/jest/node_modules/jest-message-util": {
-      "version": "29.4.2",
-      "resolved": "https://registry.npmmirror.com/jest-message-util/-/jest-message-util-29.4.2.tgz",
-      "integrity": "sha512-SElcuN4s6PNKpOEtTInjOAA8QvItu0iugkXqhYyguRvQoXapg5gN+9RQxLAkakChZA7Y26j6yUCsFWN+hlKD6g==",
+      "version": "29.4.3",
+      "resolved": "https://registry.npmmirror.com/jest-message-util/-/jest-message-util-29.4.3.tgz",
+      "integrity": "sha512-1Y8Zd4ZCN7o/QnWdMmT76If8LuDv23Z1DRovBj/vcSFNlGCJGoO8D1nJDw1AdyAGUk0myDLFGN5RbNeJyCRGCw==",
       "dependencies": {
         "@babel/code-frame": "^7.12.13",
-        "@jest/types": "^29.4.2",
+        "@jest/types": "^29.4.3",
         "@types/stack-utils": "^2.0.0",
         "chalk": "^4.0.0",
         "graceful-fs": "^4.2.9",
         "micromatch": "^4.0.4",
-        "pretty-format": "^29.4.2",
+        "pretty-format": "^29.4.3",
         "slash": "^3.0.0",
         "stack-utils": "^2.0.3"
       },
@@ -3809,11 +3821,11 @@
       }
     },
     "node_modules/@types/jest/node_modules/jest-util": {
-      "version": "29.4.2",
-      "resolved": "https://registry.npmmirror.com/jest-util/-/jest-util-29.4.2.tgz",
-      "integrity": "sha512-wKnm6XpJgzMUSRFB7YF48CuwdzuDIHenVuoIb1PLuJ6F+uErZsuDkU+EiExkChf6473XcawBrSfDSnXl+/YG4g==",
+      "version": "29.4.3",
+      "resolved": "https://registry.npmmirror.com/jest-util/-/jest-util-29.4.3.tgz",
+      "integrity": "sha512-ToSGORAz4SSSoqxDSylWX8JzkOQR7zoBtNRsA7e+1WUX5F8jrOwaNpuh1YfJHJKDHXLHmObv5eOjejUd+/Ws+Q==",
       "dependencies": {
-        "@jest/types": "^29.4.2",
+        "@jest/types": "^29.4.3",
         "@types/node": "*",
         "chalk": "^4.0.0",
         "ci-info": "^3.2.0",
@@ -3825,11 +3837,11 @@
       }
     },
     "node_modules/@types/jest/node_modules/pretty-format": {
-      "version": "29.4.2",
-      "resolved": "https://registry.npmmirror.com/pretty-format/-/pretty-format-29.4.2.tgz",
-      "integrity": "sha512-qKlHR8yFVCbcEWba0H0TOC8dnLlO4vPlyEjRPw31FZ2Rupy9nLa8ZLbYny8gWEl8CkEhJqAE6IzdNELTBVcBEg==",
+      "version": "29.4.3",
+      "resolved": "https://registry.npmmirror.com/pretty-format/-/pretty-format-29.4.3.tgz",
+      "integrity": "sha512-cvpcHTc42lcsvOOAzd3XuNWTcvk1Jmnzqeu+WsOuiPmxUJTnkbAcFNsRKvEpBEUFVUgy/GTZLulZDcDEi+CIlA==",
       "dependencies": {
-        "@jest/schemas": "^29.4.2",
+        "@jest/schemas": "^29.4.3",
         "ansi-styles": "^5.0.0",
         "react-is": "^18.0.0"
       },
@@ -3922,9 +3934,9 @@
       }
     },
     "node_modules/@types/react-dom": {
-      "version": "18.0.10",
-      "resolved": "https://registry.npmmirror.com/@types/react-dom/-/react-dom-18.0.10.tgz",
-      "integrity": "sha512-E42GW/JA4Qv15wQdqJq8DL4JhNpB3prJgjgapN3qJT9K2zO5IIAQh4VXvCEDupoqAwnz0cY4RlXeC/ajX5SFHg==",
+      "version": "18.0.11",
+      "resolved": "https://registry.npmmirror.com/@types/react-dom/-/react-dom-18.0.11.tgz",
+      "integrity": "sha512-O38bPbI2CWtgw/OoQoY+BRelw7uysmXbWvw3nLWO21H1HSh+GOlqPuXshJfjmpNlKiiSDG9cc1JZAaMmVdcTlw==",
       "dependencies": {
         "@types/react": "*"
       }
@@ -3991,9 +4003,9 @@
       }
     },
     "node_modules/@types/trusted-types": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmmirror.com/@types/trusted-types/-/trusted-types-2.0.2.tgz",
-      "integrity": "sha512-F5DIZ36YVLE+PN+Zwws4kJogq47hNgX3Nx6WyDJ3kcplxyke3XIzB8uK5n/Lpm1HBsbGzd6nmGehL8cPekP+Tg=="
+      "version": "2.0.3",
+      "resolved": "https://registry.npmmirror.com/@types/trusted-types/-/trusted-types-2.0.3.tgz",
+      "integrity": "sha512-NfQ4gyz38SL8sDNrSixxU2Os1a5xcdFxipAFxYEuLUlvU2uDwS4NUpsImcf1//SlWItCVMMLiylsxbmNMToV/g=="
     },
     "node_modules/@types/use-sync-external-store": {
       "version": "0.0.3",
@@ -5261,9 +5273,9 @@
       }
     },
     "node_modules/caniuse-lite": {
-      "version": "1.0.30001451",
-      "resolved": "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001451.tgz",
-      "integrity": "sha512-XY7UbUpGRatZzoRft//5xOa69/1iGJRBlrieH6QYrkKLIFn3m7OVEJ81dSrKoy2BnKsdbX5cLrOispZNYo9v2w=="
+      "version": "1.0.30001452",
+      "resolved": "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001452.tgz",
+      "integrity": "sha512-Lkp0vFjMkBB3GTpLR8zk4NwW5EdRdnitwYJHDOOKIU85x4ckYCPQ+9WlVvSVClHxVReefkUMtWZH2l9KGlD51w=="
     },
     "node_modules/case-sensitive-paths-webpack-plugin": {
       "version": "2.4.0",
@@ -5858,11 +5870,11 @@
       }
     },
     "node_modules/cssnano": {
-      "version": "5.1.14",
-      "resolved": "https://registry.npmmirror.com/cssnano/-/cssnano-5.1.14.tgz",
-      "integrity": "sha512-Oou7ihiTocbKqi0J1bB+TRJIQX5RMR3JghA8hcWSw9mjBLQ5Y3RWqEDoYG3sRNlAbCIXpqMoZGbq5KDR3vdzgw==",
+      "version": "5.1.15",
+      "resolved": "https://registry.npmmirror.com/cssnano/-/cssnano-5.1.15.tgz",
+      "integrity": "sha512-j+BKgDcLDQA+eDifLx0EO4XSA56b7uut3BQFH+wbSaSTuGLuiyTa/wbRYthUXX8LC9mLg+WWKe8h+qJuwTAbHw==",
       "dependencies": {
-        "cssnano-preset-default": "^5.2.13",
+        "cssnano-preset-default": "^5.2.14",
         "lilconfig": "^2.0.3",
         "yaml": "^1.10.2"
       },
@@ -5874,21 +5886,21 @@
       }
     },
     "node_modules/cssnano-preset-default": {
-      "version": "5.2.13",
-      "resolved": "https://registry.npmmirror.com/cssnano-preset-default/-/cssnano-preset-default-5.2.13.tgz",
-      "integrity": "sha512-PX7sQ4Pb+UtOWuz8A1d+Rbi+WimBIxJTRyBdgGp1J75VU0r/HFQeLnMYgHiCAp6AR4rqrc7Y4R+1Rjk3KJz6DQ==",
+      "version": "5.2.14",
+      "resolved": "https://registry.npmmirror.com/cssnano-preset-default/-/cssnano-preset-default-5.2.14.tgz",
+      "integrity": "sha512-t0SFesj/ZV2OTylqQVOrFgEh5uanxbO6ZAdeCrNsUQ6fVuXwYTxJPNAGvGTxHbD68ldIJNec7PyYZDBrfDQ+6A==",
       "dependencies": {
         "css-declaration-sorter": "^6.3.1",
         "cssnano-utils": "^3.1.0",
         "postcss-calc": "^8.2.3",
-        "postcss-colormin": "^5.3.0",
+        "postcss-colormin": "^5.3.1",
         "postcss-convert-values": "^5.1.3",
         "postcss-discard-comments": "^5.1.2",
         "postcss-discard-duplicates": "^5.1.0",
         "postcss-discard-empty": "^5.1.1",
         "postcss-discard-overridden": "^5.1.0",
         "postcss-merge-longhand": "^5.1.7",
-        "postcss-merge-rules": "^5.1.3",
+        "postcss-merge-rules": "^5.1.4",
         "postcss-minify-font-values": "^5.1.0",
         "postcss-minify-gradients": "^5.1.1",
         "postcss-minify-params": "^5.1.4",
@@ -5903,7 +5915,7 @@
         "postcss-normalize-url": "^5.1.0",
         "postcss-normalize-whitespace": "^5.1.1",
         "postcss-ordered-values": "^5.1.3",
-        "postcss-reduce-initial": "^5.1.1",
+        "postcss-reduce-initial": "^5.1.2",
         "postcss-reduce-transforms": "^5.1.0",
         "postcss-svgo": "^5.1.0",
         "postcss-unique-selectors": "^5.1.1"
@@ -6359,9 +6371,9 @@
       }
     },
     "node_modules/electron-to-chromium": {
-      "version": "1.4.295",
-      "resolved": "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.4.295.tgz",
-      "integrity": "sha512-lEO94zqf1bDA3aepxwnWoHUjA8sZ+2owgcSZjYQy0+uOSEclJX0VieZC+r+wLpSxUHRd6gG32znTWmr+5iGzFw=="
+      "version": "1.4.297",
+      "resolved": "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.4.297.tgz",
+      "integrity": "sha512-dTXLXBdzfDYnZYq+bLer21HrFsEkzlR2OSIOsR+qroDmhmQU3i4T4KdY0Lcp83ZId3HnWTpPAEfhaJtVxmS/dQ=="
     },
     "node_modules/emittery": {
       "version": "0.8.1",
@@ -6951,9 +6963,9 @@
       }
     },
     "node_modules/eslint-plugin-testing-library": {
-      "version": "5.10.1",
-      "resolved": "https://registry.npmmirror.com/eslint-plugin-testing-library/-/eslint-plugin-testing-library-5.10.1.tgz",
-      "integrity": "sha512-GRy87AqUi2Ij69pe0YnOXm3oGBCgnFwfIv+Hu9q/kT3jL0pX1cXA7aO+oJnvdpbJy2+riOPqGsa3iAkL888NLg==",
+      "version": "5.10.2",
+      "resolved": "https://registry.npmmirror.com/eslint-plugin-testing-library/-/eslint-plugin-testing-library-5.10.2.tgz",
+      "integrity": "sha512-f1DmDWcz5SDM+IpCkEX0lbFqrrTs8HRsEElzDEqN/EBI0hpRj8Cns5+IVANXswE8/LeybIJqPAOQIFu2j5Y5sw==",
       "dependencies": {
         "@typescript-eslint/utils": "^5.43.0"
       },
@@ -12018,11 +12030,11 @@
       }
     },
     "node_modules/postcss-colormin": {
-      "version": "5.3.0",
-      "resolved": "https://registry.npmmirror.com/postcss-colormin/-/postcss-colormin-5.3.0.tgz",
-      "integrity": "sha512-WdDO4gOFG2Z8n4P8TWBpshnL3JpmNmJwdnfP2gbk2qBA8PWwOYcmjmI/t3CmMeL72a7Hkd+x/Mg9O2/0rD54Pg==",
+      "version": "5.3.1",
+      "resolved": "https://registry.npmmirror.com/postcss-colormin/-/postcss-colormin-5.3.1.tgz",
+      "integrity": "sha512-UsWQG0AqTFQmpBegeLLc1+c3jIqBNB0zlDGRWR+dQ3pRKJL1oeMzyqmH3o2PIfn9MBdNrVPWhDbT769LxCTLJQ==",
       "dependencies": {
-        "browserslist": "^4.16.6",
+        "browserslist": "^4.21.4",
         "caniuse-api": "^3.0.0",
         "colord": "^2.9.1",
         "postcss-value-parser": "^4.2.0"
@@ -12379,9 +12391,9 @@
       }
     },
     "node_modules/postcss-merge-rules": {
-      "version": "5.1.3",
-      "resolved": "https://registry.npmmirror.com/postcss-merge-rules/-/postcss-merge-rules-5.1.3.tgz",
-      "integrity": "sha512-LbLd7uFC00vpOuMvyZop8+vvhnfRGpp2S+IMQKeuOZZapPRY4SMq5ErjQeHbHsjCUgJkRNrlU+LmxsKIqPKQlA==",
+      "version": "5.1.4",
+      "resolved": "https://registry.npmmirror.com/postcss-merge-rules/-/postcss-merge-rules-5.1.4.tgz",
+      "integrity": "sha512-0R2IuYpgU93y9lhVbO/OylTtKMVcHb67zjWIfCiKR9rWL3GUk1677LAqD/BcHizukdZEjT8Ru3oHRoAYoJy44g==",
       "dependencies": {
         "browserslist": "^4.21.4",
         "caniuse-api": "^3.0.0",
@@ -12820,9 +12832,9 @@
       }
     },
     "node_modules/postcss-reduce-initial": {
-      "version": "5.1.1",
-      "resolved": "https://registry.npmmirror.com/postcss-reduce-initial/-/postcss-reduce-initial-5.1.1.tgz",
-      "integrity": "sha512-//jeDqWcHPuXGZLoolFrUXBDyuEGbr9S2rMo19bkTIjBQ4PqkaO+oI8wua5BOUxpfi97i3PCoInsiFIEBfkm9w==",
+      "version": "5.1.2",
+      "resolved": "https://registry.npmmirror.com/postcss-reduce-initial/-/postcss-reduce-initial-5.1.2.tgz",
+      "integrity": "sha512-dE/y2XRaqAi6OvjzD22pjTUQ8eOfc6m/natGHgKFBK9DxFmIm69YmaRVQrGgFlEfc1HePIurY0TmDeROK05rIg==",
       "dependencies": {
         "browserslist": "^4.21.4",
         "caniuse-api": "^3.0.0"
@@ -13391,6 +13403,36 @@
         "node": ">=0.10.0"
       }
     },
+    "node_modules/react-router": {
+      "version": "6.8.1",
+      "resolved": "https://registry.npmmirror.com/react-router/-/react-router-6.8.1.tgz",
+      "integrity": "sha512-Jgi8BzAJQ8MkPt8ipXnR73rnD7EmZ0HFFb7jdQU24TynGW1Ooqin2KVDN9voSC+7xhqbbCd2cjGUepb6RObnyg==",
+      "dependencies": {
+        "@remix-run/router": "1.3.2"
+      },
+      "engines": {
+        "node": ">=14"
+      },
+      "peerDependencies": {
+        "react": ">=16.8"
+      }
+    },
+    "node_modules/react-router-dom": {
+      "version": "6.8.1",
+      "resolved": "https://registry.npmmirror.com/react-router-dom/-/react-router-dom-6.8.1.tgz",
+      "integrity": "sha512-67EXNfkQgf34P7+PSb6VlBuaacGhkKn3kpE51+P6zYSG2kiRoumXEL6e27zTa9+PGF2MNXbgIUHTVlleLbIcHQ==",
+      "dependencies": {
+        "@remix-run/router": "1.3.2",
+        "react-router": "6.8.1"
+      },
+      "engines": {
+        "node": ">=14"
+      },
+      "peerDependencies": {
+        "react": ">=16.8",
+        "react-dom": ">=16.8"
+      }
+    },
     "node_modules/react-scripts": {
       "version": "5.0.1",
       "resolved": "https://registry.npmmirror.com/react-scripts/-/react-scripts-5.0.1.tgz",
@@ -17754,17 +17796,17 @@
       }
     },
     "@jest/expect-utils": {
-      "version": "29.4.2",
-      "resolved": "https://registry.npmmirror.com/@jest/expect-utils/-/expect-utils-29.4.2.tgz",
-      "integrity": "sha512-Dd3ilDJpBnqa0GiPN7QrudVs0cczMMHtehSo2CSTjm3zdHx0RcpmhFNVEltuEFeqfLIyWKFI224FsMSQ/nsJQA==",
+      "version": "29.4.3",
+      "resolved": "https://registry.npmmirror.com/@jest/expect-utils/-/expect-utils-29.4.3.tgz",
+      "integrity": "sha512-/6JWbkxHOP8EoS8jeeTd9dTfc9Uawi+43oLKHfp6zzux3U2hqOOVnV3ai4RpDYHOccL6g+5nrxpoc8DmJxtXVQ==",
       "requires": {
-        "jest-get-type": "^29.4.2"
+        "jest-get-type": "^29.4.3"
       },
       "dependencies": {
         "jest-get-type": {
-          "version": "29.4.2",
-          "resolved": "https://registry.npmmirror.com/jest-get-type/-/jest-get-type-29.4.2.tgz",
-          "integrity": "sha512-vERN30V5i2N6lqlFu4ljdTqQAgrkTFMC9xaIIfOPYBw04pufjXRty5RuXBiB1d72tGbURa/UgoiHB90ruOSivg=="
+          "version": "29.4.3",
+          "resolved": "https://registry.npmmirror.com/jest-get-type/-/jest-get-type-29.4.3.tgz",
+          "integrity": "sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg=="
         }
       }
     },
@@ -18182,6 +18224,11 @@
         "reselect": "^4.1.7"
       }
     },
+    "@remix-run/router": {
+      "version": "1.3.2",
+      "resolved": "https://registry.npmmirror.com/@remix-run/router/-/router-1.3.2.tgz",
+      "integrity": "sha512-t54ONhl/h75X94SWsHGQ4G/ZrCEguKSRQr7DrjTciJXW0YU1QhlwYeycvK5JgkzlxmvrK7wq1NB/PLtHxoiDcA=="
+    },
     "@rollup/plugin-babel": {
       "version": "5.3.1",
       "resolved": "https://registry.npmmirror.com/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz",
@@ -18508,10 +18555,12 @@
       }
     },
     "@testing-library/user-event": {
-      "version": "14.4.3",
-      "resolved": "https://registry.npmmirror.com/@testing-library/user-event/-/user-event-14.4.3.tgz",
-      "integrity": "sha512-kCUc5MEwaEMakkO5x7aoD+DLi02ehmEM2QCGWvNqAS1dV/fAvORWEjnjsEIvml59M7Y5kCkWN6fCCyPOe8OL6Q==",
-      "requires": {}
+      "version": "13.5.0",
+      "resolved": "https://registry.npmmirror.com/@testing-library/user-event/-/user-event-13.5.0.tgz",
+      "integrity": "sha512-5Kwtbo3Y/NowpkbRuSepbyMFkZmHgD+vPzYB/RJ4oxt5Gj/avFFBYjhw27cqSVPVw/3a67NK1PbiIr9k4Gwmdg==",
+      "requires": {
+        "@babel/runtime": "^7.12.5"
+      }
     },
     "@tootallnate/once": {
       "version": "1.1.2",
@@ -18600,9 +18649,9 @@
       }
     },
     "@types/eslint": {
-      "version": "8.21.0",
-      "resolved": "https://registry.npmmirror.com/@types/eslint/-/eslint-8.21.0.tgz",
-      "integrity": "sha512-35EhHNOXgxnUgh4XCJsGhE7zdlDhYDN/aMG6UbkByCFFNgQ7b3U+uVoqBpicFydR8JEfgdjCF7SJ7MiJfzuiTA==",
+      "version": "8.21.1",
+      "resolved": "https://registry.npmmirror.com/@types/eslint/-/eslint-8.21.1.tgz",
+      "integrity": "sha512-rc9K8ZpVjNcLs8Fp0dkozd5Pt2Apk1glO4Vgz8ix1u6yFByxfqo5Yavpy65o+93TAe24jr7v+eSBtFLvOQtCRQ==",
       "requires": {
         "@types/estree": "*",
         "@types/json-schema": "*"
@@ -18704,19 +18753,19 @@
       },
       "dependencies": {
         "@jest/schemas": {
-          "version": "29.4.2",
-          "resolved": "https://registry.npmmirror.com/@jest/schemas/-/schemas-29.4.2.tgz",
-          "integrity": "sha512-ZrGzGfh31NtdVH8tn0mgJw4khQuNHiKqdzJAFbCaERbyCP9tHlxWuL/mnMu8P7e/+k4puWjI1NOzi/sFsjce/g==",
+          "version": "29.4.3",
+          "resolved": "https://registry.npmmirror.com/@jest/schemas/-/schemas-29.4.3.tgz",
+          "integrity": "sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg==",
           "requires": {
             "@sinclair/typebox": "^0.25.16"
           }
         },
         "@jest/types": {
-          "version": "29.4.2",
-          "resolved": "https://registry.npmmirror.com/@jest/types/-/types-29.4.2.tgz",
-          "integrity": "sha512-CKlngyGP0fwlgC1BRUtPZSiWLBhyS9dKwKmyGxk8Z6M82LBEGB2aLQSg+U1MyLsU+M7UjnlLllBM2BLWKVm/Uw==",
+          "version": "29.4.3",
+          "resolved": "https://registry.npmmirror.com/@jest/types/-/types-29.4.3.tgz",
+          "integrity": "sha512-bPYfw8V65v17m2Od1cv44FH+SiKW7w2Xu7trhcdTLUmSv85rfKsP+qXSjO4KGJr4dtPSzl/gvslZBXctf1qGEA==",
           "requires": {
-            "@jest/schemas": "^29.4.2",
+            "@jest/schemas": "^29.4.3",
             "@types/istanbul-lib-coverage": "^2.0.0",
             "@types/istanbul-reports": "^3.0.0",
             "@types/node": "*",
@@ -18725,9 +18774,9 @@
           }
         },
         "@sinclair/typebox": {
-          "version": "0.25.21",
-          "resolved": "https://registry.npmmirror.com/@sinclair/typebox/-/typebox-0.25.21.tgz",
-          "integrity": "sha512-gFukHN4t8K4+wVC+ECqeqwzBDeFeTzBXroBTqE6vcWrQGbEUpHO7LYdG0f4xnvYq4VOEwITSlHlp0JBAIFMS/g=="
+          "version": "0.25.22",
+          "resolved": "https://registry.npmmirror.com/@sinclair/typebox/-/typebox-0.25.22.tgz",
+          "integrity": "sha512-6U6r2L7rnM7EG8G1tWzIjdB3QlsHF4slgcqXNN/SF0xJOAr0nDmT2GedlkyO3mrv8mDTJ24UuOMWR3diBrCvQQ=="
         },
         "@types/yargs": {
           "version": "17.0.22",
@@ -18768,20 +18817,20 @@
           "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
         },
         "diff-sequences": {
-          "version": "29.4.2",
-          "resolved": "https://registry.npmmirror.com/diff-sequences/-/diff-sequences-29.4.2.tgz",
-          "integrity": "sha512-R6P0Y6PrsH3n4hUXxL3nns0rbRk6Q33js3ygJBeEpbzLzgcNuJ61+u0RXasFpTKISw99TxUzFnumSnRLsjhLaw=="
+          "version": "29.4.3",
+          "resolved": "https://registry.npmmirror.com/diff-sequences/-/diff-sequences-29.4.3.tgz",
+          "integrity": "sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA=="
         },
         "expect": {
-          "version": "29.4.2",
-          "resolved": "https://registry.npmmirror.com/expect/-/expect-29.4.2.tgz",
-          "integrity": "sha512-+JHYg9O3hd3RlICG90OPVjRkPBoiUH7PxvDVMnRiaq1g6JUgZStX514erMl0v2Dc5SkfVbm7ztqbd6qHHPn+mQ==",
+          "version": "29.4.3",
+          "resolved": "https://registry.npmmirror.com/expect/-/expect-29.4.3.tgz",
+          "integrity": "sha512-uC05+Q7eXECFpgDrHdXA4k2rpMyStAYPItEDLyQDo5Ta7fVkJnNA/4zh/OIVkVVNZ1oOK1PipQoyNjuZ6sz6Dg==",
           "requires": {
-            "@jest/expect-utils": "^29.4.2",
-            "jest-get-type": "^29.4.2",
-            "jest-matcher-utils": "^29.4.2",
-            "jest-message-util": "^29.4.2",
-            "jest-util": "^29.4.2"
+            "@jest/expect-utils": "^29.4.3",
+            "jest-get-type": "^29.4.3",
+            "jest-matcher-utils": "^29.4.3",
+            "jest-message-util": "^29.4.3",
+            "jest-util": "^29.4.3"
           }
         },
         "has-flag": {
@@ -18790,54 +18839,54 @@
           "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="
         },
         "jest-diff": {
-          "version": "29.4.2",
-          "resolved": "https://registry.npmmirror.com/jest-diff/-/jest-diff-29.4.2.tgz",
-          "integrity": "sha512-EK8DSajVtnjx9sa1BkjZq3mqChm2Cd8rIzdXkQMA8e0wuXq53ypz6s5o5V8HRZkoEt2ywJ3eeNWFKWeYr8HK4g==",
+          "version": "29.4.3",
+          "resolved": "https://registry.npmmirror.com/jest-diff/-/jest-diff-29.4.3.tgz",
+          "integrity": "sha512-YB+ocenx7FZ3T5O9lMVMeLYV4265socJKtkwgk/6YUz/VsEzYDkiMuMhWzZmxm3wDRQvayJu/PjkjjSkjoHsCA==",
           "requires": {
             "chalk": "^4.0.0",
-            "diff-sequences": "^29.4.2",
-            "jest-get-type": "^29.4.2",
-            "pretty-format": "^29.4.2"
+            "diff-sequences": "^29.4.3",
+            "jest-get-type": "^29.4.3",
+            "pretty-format": "^29.4.3"
           }
         },
         "jest-get-type": {
-          "version": "29.4.2",
-          "resolved": "https://registry.npmmirror.com/jest-get-type/-/jest-get-type-29.4.2.tgz",
-          "integrity": "sha512-vERN30V5i2N6lqlFu4ljdTqQAgrkTFMC9xaIIfOPYBw04pufjXRty5RuXBiB1d72tGbURa/UgoiHB90ruOSivg=="
+          "version": "29.4.3",
+          "resolved": "https://registry.npmmirror.com/jest-get-type/-/jest-get-type-29.4.3.tgz",
+          "integrity": "sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg=="
         },
         "jest-matcher-utils": {
-          "version": "29.4.2",
-          "resolved": "https://registry.npmmirror.com/jest-matcher-utils/-/jest-matcher-utils-29.4.2.tgz",
-          "integrity": "sha512-EZaAQy2je6Uqkrm6frnxBIdaWtSYFoR8SVb2sNLAtldswlR/29JAgx+hy67llT3+hXBaLB0zAm5UfeqerioZyg==",
+          "version": "29.4.3",
+          "resolved": "https://registry.npmmirror.com/jest-matcher-utils/-/jest-matcher-utils-29.4.3.tgz",
+          "integrity": "sha512-TTciiXEONycZ03h6R6pYiZlSkvYgT0l8aa49z/DLSGYjex4orMUcafuLXYyyEDWB1RKglq00jzwY00Ei7yFNVg==",
           "requires": {
             "chalk": "^4.0.0",
-            "jest-diff": "^29.4.2",
-            "jest-get-type": "^29.4.2",
-            "pretty-format": "^29.4.2"
+            "jest-diff": "^29.4.3",
+            "jest-get-type": "^29.4.3",
+            "pretty-format": "^29.4.3"
           }
         },
         "jest-message-util": {
-          "version": "29.4.2",
-          "resolved": "https://registry.npmmirror.com/jest-message-util/-/jest-message-util-29.4.2.tgz",
-          "integrity": "sha512-SElcuN4s6PNKpOEtTInjOAA8QvItu0iugkXqhYyguRvQoXapg5gN+9RQxLAkakChZA7Y26j6yUCsFWN+hlKD6g==",
+          "version": "29.4.3",
+          "resolved": "https://registry.npmmirror.com/jest-message-util/-/jest-message-util-29.4.3.tgz",
+          "integrity": "sha512-1Y8Zd4ZCN7o/QnWdMmT76If8LuDv23Z1DRovBj/vcSFNlGCJGoO8D1nJDw1AdyAGUk0myDLFGN5RbNeJyCRGCw==",
           "requires": {
             "@babel/code-frame": "^7.12.13",
-            "@jest/types": "^29.4.2",
+            "@jest/types": "^29.4.3",
             "@types/stack-utils": "^2.0.0",
             "chalk": "^4.0.0",
             "graceful-fs": "^4.2.9",
             "micromatch": "^4.0.4",
-            "pretty-format": "^29.4.2",
+            "pretty-format": "^29.4.3",
             "slash": "^3.0.0",
             "stack-utils": "^2.0.3"
           }
         },
         "jest-util": {
-          "version": "29.4.2",
-          "resolved": "https://registry.npmmirror.com/jest-util/-/jest-util-29.4.2.tgz",
-          "integrity": "sha512-wKnm6XpJgzMUSRFB7YF48CuwdzuDIHenVuoIb1PLuJ6F+uErZsuDkU+EiExkChf6473XcawBrSfDSnXl+/YG4g==",
+          "version": "29.4.3",
+          "resolved": "https://registry.npmmirror.com/jest-util/-/jest-util-29.4.3.tgz",
+          "integrity": "sha512-ToSGORAz4SSSoqxDSylWX8JzkOQR7zoBtNRsA7e+1WUX5F8jrOwaNpuh1YfJHJKDHXLHmObv5eOjejUd+/Ws+Q==",
           "requires": {
-            "@jest/types": "^29.4.2",
+            "@jest/types": "^29.4.3",
             "@types/node": "*",
             "chalk": "^4.0.0",
             "ci-info": "^3.2.0",
@@ -18846,11 +18895,11 @@
           }
         },
         "pretty-format": {
-          "version": "29.4.2",
-          "resolved": "https://registry.npmmirror.com/pretty-format/-/pretty-format-29.4.2.tgz",
-          "integrity": "sha512-qKlHR8yFVCbcEWba0H0TOC8dnLlO4vPlyEjRPw31FZ2Rupy9nLa8ZLbYny8gWEl8CkEhJqAE6IzdNELTBVcBEg==",
+          "version": "29.4.3",
+          "resolved": "https://registry.npmmirror.com/pretty-format/-/pretty-format-29.4.3.tgz",
+          "integrity": "sha512-cvpcHTc42lcsvOOAzd3XuNWTcvk1Jmnzqeu+WsOuiPmxUJTnkbAcFNsRKvEpBEUFVUgy/GTZLulZDcDEi+CIlA==",
           "requires": {
-            "@jest/schemas": "^29.4.2",
+            "@jest/schemas": "^29.4.3",
             "ansi-styles": "^5.0.0",
             "react-is": "^18.0.0"
           },
@@ -18938,9 +18987,9 @@
       }
     },
     "@types/react-dom": {
-      "version": "18.0.10",
-      "resolved": "https://registry.npmmirror.com/@types/react-dom/-/react-dom-18.0.10.tgz",
-      "integrity": "sha512-E42GW/JA4Qv15wQdqJq8DL4JhNpB3prJgjgapN3qJT9K2zO5IIAQh4VXvCEDupoqAwnz0cY4RlXeC/ajX5SFHg==",
+      "version": "18.0.11",
+      "resolved": "https://registry.npmmirror.com/@types/react-dom/-/react-dom-18.0.11.tgz",
+      "integrity": "sha512-O38bPbI2CWtgw/OoQoY+BRelw7uysmXbWvw3nLWO21H1HSh+GOlqPuXshJfjmpNlKiiSDG9cc1JZAaMmVdcTlw==",
       "requires": {
         "@types/react": "*"
       }
@@ -19007,9 +19056,9 @@
       }
     },
     "@types/trusted-types": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmmirror.com/@types/trusted-types/-/trusted-types-2.0.2.tgz",
-      "integrity": "sha512-F5DIZ36YVLE+PN+Zwws4kJogq47hNgX3Nx6WyDJ3kcplxyke3XIzB8uK5n/Lpm1HBsbGzd6nmGehL8cPekP+Tg=="
+      "version": "2.0.3",
+      "resolved": "https://registry.npmmirror.com/@types/trusted-types/-/trusted-types-2.0.3.tgz",
+      "integrity": "sha512-NfQ4gyz38SL8sDNrSixxU2Os1a5xcdFxipAFxYEuLUlvU2uDwS4NUpsImcf1//SlWItCVMMLiylsxbmNMToV/g=="
     },
     "@types/use-sync-external-store": {
       "version": "0.0.3",
@@ -20019,9 +20068,9 @@
       }
     },
     "caniuse-lite": {
-      "version": "1.0.30001451",
-      "resolved": "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001451.tgz",
-      "integrity": "sha512-XY7UbUpGRatZzoRft//5xOa69/1iGJRBlrieH6QYrkKLIFn3m7OVEJ81dSrKoy2BnKsdbX5cLrOispZNYo9v2w=="
+      "version": "1.0.30001452",
+      "resolved": "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001452.tgz",
+      "integrity": "sha512-Lkp0vFjMkBB3GTpLR8zk4NwW5EdRdnitwYJHDOOKIU85x4ckYCPQ+9WlVvSVClHxVReefkUMtWZH2l9KGlD51w=="
     },
     "case-sensitive-paths-webpack-plugin": {
       "version": "2.4.0",
@@ -20471,31 +20520,31 @@
       "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="
     },
     "cssnano": {
-      "version": "5.1.14",
-      "resolved": "https://registry.npmmirror.com/cssnano/-/cssnano-5.1.14.tgz",
-      "integrity": "sha512-Oou7ihiTocbKqi0J1bB+TRJIQX5RMR3JghA8hcWSw9mjBLQ5Y3RWqEDoYG3sRNlAbCIXpqMoZGbq5KDR3vdzgw==",
+      "version": "5.1.15",
+      "resolved": "https://registry.npmmirror.com/cssnano/-/cssnano-5.1.15.tgz",
+      "integrity": "sha512-j+BKgDcLDQA+eDifLx0EO4XSA56b7uut3BQFH+wbSaSTuGLuiyTa/wbRYthUXX8LC9mLg+WWKe8h+qJuwTAbHw==",
       "requires": {
-        "cssnano-preset-default": "^5.2.13",
+        "cssnano-preset-default": "^5.2.14",
         "lilconfig": "^2.0.3",
         "yaml": "^1.10.2"
       }
     },
     "cssnano-preset-default": {
-      "version": "5.2.13",
-      "resolved": "https://registry.npmmirror.com/cssnano-preset-default/-/cssnano-preset-default-5.2.13.tgz",
-      "integrity": "sha512-PX7sQ4Pb+UtOWuz8A1d+Rbi+WimBIxJTRyBdgGp1J75VU0r/HFQeLnMYgHiCAp6AR4rqrc7Y4R+1Rjk3KJz6DQ==",
+      "version": "5.2.14",
+      "resolved": "https://registry.npmmirror.com/cssnano-preset-default/-/cssnano-preset-default-5.2.14.tgz",
+      "integrity": "sha512-t0SFesj/ZV2OTylqQVOrFgEh5uanxbO6ZAdeCrNsUQ6fVuXwYTxJPNAGvGTxHbD68ldIJNec7PyYZDBrfDQ+6A==",
       "requires": {
         "css-declaration-sorter": "^6.3.1",
         "cssnano-utils": "^3.1.0",
         "postcss-calc": "^8.2.3",
-        "postcss-colormin": "^5.3.0",
+        "postcss-colormin": "^5.3.1",
         "postcss-convert-values": "^5.1.3",
         "postcss-discard-comments": "^5.1.2",
         "postcss-discard-duplicates": "^5.1.0",
         "postcss-discard-empty": "^5.1.1",
         "postcss-discard-overridden": "^5.1.0",
         "postcss-merge-longhand": "^5.1.7",
-        "postcss-merge-rules": "^5.1.3",
+        "postcss-merge-rules": "^5.1.4",
         "postcss-minify-font-values": "^5.1.0",
         "postcss-minify-gradients": "^5.1.1",
         "postcss-minify-params": "^5.1.4",
@@ -20510,7 +20559,7 @@
         "postcss-normalize-url": "^5.1.0",
         "postcss-normalize-whitespace": "^5.1.1",
         "postcss-ordered-values": "^5.1.3",
-        "postcss-reduce-initial": "^5.1.1",
+        "postcss-reduce-initial": "^5.1.2",
         "postcss-reduce-transforms": "^5.1.0",
         "postcss-svgo": "^5.1.0",
         "postcss-unique-selectors": "^5.1.1"
@@ -20872,9 +20921,9 @@
       }
     },
     "electron-to-chromium": {
-      "version": "1.4.295",
-      "resolved": "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.4.295.tgz",
-      "integrity": "sha512-lEO94zqf1bDA3aepxwnWoHUjA8sZ+2owgcSZjYQy0+uOSEclJX0VieZC+r+wLpSxUHRd6gG32znTWmr+5iGzFw=="
+      "version": "1.4.297",
+      "resolved": "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.4.297.tgz",
+      "integrity": "sha512-dTXLXBdzfDYnZYq+bLer21HrFsEkzlR2OSIOsR+qroDmhmQU3i4T4KdY0Lcp83ZId3HnWTpPAEfhaJtVxmS/dQ=="
     },
     "emittery": {
       "version": "0.8.1",
@@ -21417,9 +21466,9 @@
       "requires": {}
     },
     "eslint-plugin-testing-library": {
-      "version": "5.10.1",
-      "resolved": "https://registry.npmmirror.com/eslint-plugin-testing-library/-/eslint-plugin-testing-library-5.10.1.tgz",
-      "integrity": "sha512-GRy87AqUi2Ij69pe0YnOXm3oGBCgnFwfIv+Hu9q/kT3jL0pX1cXA7aO+oJnvdpbJy2+riOPqGsa3iAkL888NLg==",
+      "version": "5.10.2",
+      "resolved": "https://registry.npmmirror.com/eslint-plugin-testing-library/-/eslint-plugin-testing-library-5.10.2.tgz",
+      "integrity": "sha512-f1DmDWcz5SDM+IpCkEX0lbFqrrTs8HRsEElzDEqN/EBI0hpRj8Cns5+IVANXswE8/LeybIJqPAOQIFu2j5Y5sw==",
       "requires": {
         "@typescript-eslint/utils": "^5.43.0"
       }
@@ -25256,11 +25305,11 @@
       }
     },
     "postcss-colormin": {
-      "version": "5.3.0",
-      "resolved": "https://registry.npmmirror.com/postcss-colormin/-/postcss-colormin-5.3.0.tgz",
-      "integrity": "sha512-WdDO4gOFG2Z8n4P8TWBpshnL3JpmNmJwdnfP2gbk2qBA8PWwOYcmjmI/t3CmMeL72a7Hkd+x/Mg9O2/0rD54Pg==",
+      "version": "5.3.1",
+      "resolved": "https://registry.npmmirror.com/postcss-colormin/-/postcss-colormin-5.3.1.tgz",
+      "integrity": "sha512-UsWQG0AqTFQmpBegeLLc1+c3jIqBNB0zlDGRWR+dQ3pRKJL1oeMzyqmH3o2PIfn9MBdNrVPWhDbT769LxCTLJQ==",
       "requires": {
-        "browserslist": "^4.16.6",
+        "browserslist": "^4.21.4",
         "caniuse-api": "^3.0.0",
         "colord": "^2.9.1",
         "postcss-value-parser": "^4.2.0"
@@ -25464,9 +25513,9 @@
       }
     },
     "postcss-merge-rules": {
-      "version": "5.1.3",
-      "resolved": "https://registry.npmmirror.com/postcss-merge-rules/-/postcss-merge-rules-5.1.3.tgz",
-      "integrity": "sha512-LbLd7uFC00vpOuMvyZop8+vvhnfRGpp2S+IMQKeuOZZapPRY4SMq5ErjQeHbHsjCUgJkRNrlU+LmxsKIqPKQlA==",
+      "version": "5.1.4",
+      "resolved": "https://registry.npmmirror.com/postcss-merge-rules/-/postcss-merge-rules-5.1.4.tgz",
+      "integrity": "sha512-0R2IuYpgU93y9lhVbO/OylTtKMVcHb67zjWIfCiKR9rWL3GUk1677LAqD/BcHizukdZEjT8Ru3oHRoAYoJy44g==",
       "requires": {
         "browserslist": "^4.21.4",
         "caniuse-api": "^3.0.0",
@@ -25743,9 +25792,9 @@
       }
     },
     "postcss-reduce-initial": {
-      "version": "5.1.1",
-      "resolved": "https://registry.npmmirror.com/postcss-reduce-initial/-/postcss-reduce-initial-5.1.1.tgz",
-      "integrity": "sha512-//jeDqWcHPuXGZLoolFrUXBDyuEGbr9S2rMo19bkTIjBQ4PqkaO+oI8wua5BOUxpfi97i3PCoInsiFIEBfkm9w==",
+      "version": "5.1.2",
+      "resolved": "https://registry.npmmirror.com/postcss-reduce-initial/-/postcss-reduce-initial-5.1.2.tgz",
+      "integrity": "sha512-dE/y2XRaqAi6OvjzD22pjTUQ8eOfc6m/natGHgKFBK9DxFmIm69YmaRVQrGgFlEfc1HePIurY0TmDeROK05rIg==",
       "requires": {
         "browserslist": "^4.21.4",
         "caniuse-api": "^3.0.0"
@@ -26171,6 +26220,23 @@
       "resolved": "https://registry.npmmirror.com/react-refresh/-/react-refresh-0.11.0.tgz",
       "integrity": "sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A=="
     },
+    "react-router": {
+      "version": "6.8.1",
+      "resolved": "https://registry.npmmirror.com/react-router/-/react-router-6.8.1.tgz",
+      "integrity": "sha512-Jgi8BzAJQ8MkPt8ipXnR73rnD7EmZ0HFFb7jdQU24TynGW1Ooqin2KVDN9voSC+7xhqbbCd2cjGUepb6RObnyg==",
+      "requires": {
+        "@remix-run/router": "1.3.2"
+      }
+    },
+    "react-router-dom": {
+      "version": "6.8.1",
+      "resolved": "https://registry.npmmirror.com/react-router-dom/-/react-router-dom-6.8.1.tgz",
+      "integrity": "sha512-67EXNfkQgf34P7+PSb6VlBuaacGhkKn3kpE51+P6zYSG2kiRoumXEL6e27zTa9+PGF2MNXbgIUHTVlleLbIcHQ==",
+      "requires": {
+        "@remix-run/router": "1.3.2",
+        "react-router": "6.8.1"
+      }
+    },
     "react-scripts": {
       "version": "5.0.1",
       "resolved": "https://registry.npmmirror.com/react-scripts/-/react-scripts-5.0.1.tgz",

+ 3 - 2
15_React/day-6/code/my-app/package.json → 15_React/day-6/code/learn-redux/package.json

@@ -1,15 +1,16 @@
 {
-  "name": "my-app",
+  "name": "learn-redux",
   "version": "0.1.0",
   "private": true,
   "dependencies": {
     "@reduxjs/toolkit": "^1.9.2",
     "@testing-library/jest-dom": "^5.16.5",
     "@testing-library/react": "^13.4.0",
-    "@testing-library/user-event": "^14.4.3",
+    "@testing-library/user-event": "^13.5.0",
     "react": "^18.2.0",
     "react-dom": "^18.2.0",
     "react-redux": "^8.0.5",
+    "react-router-dom": "^6.8.1",
     "react-scripts": "5.0.1",
     "web-vitals": "^2.1.4"
   },

BIN
15_React/day-6/code/learn-redux/public/favicon.ico


+ 1 - 1
15_React/day-6/code/my-app/public/index.html → 15_React/day-6/code/learn-redux/public/index.html

@@ -24,7 +24,7 @@
       work correctly both with client-side routing and a non-root public URL.
       Learn how to configure a non-root public URL by running `npm run build`.
     -->
-    <title>React Redux App</title>
+    <title>React App</title>
   </head>
   <body>
     <noscript>You need to enable JavaScript to run this app.</noscript>

BIN
15_React/day-6/code/learn-redux/public/logo192.png


BIN
15_React/day-6/code/learn-redux/public/logo512.png


+ 0 - 0
15_React/day-6/code/my-app/public/manifest.json → 15_React/day-6/code/learn-redux/public/manifest.json


+ 1 - 0
15_React/day-6/code/my-app/public/robots.txt → 15_React/day-6/code/learn-redux/public/robots.txt

@@ -1,2 +1,3 @@
 # https://www.robotstxt.org/robotstxt.html
 User-agent: *
+Disallow:

+ 9 - 10
15_React/day-6/code/my-app/src/App.css → 15_React/day-6/code/learn-redux/src/App.css

@@ -9,31 +9,30 @@
 
 @media (prefers-reduced-motion: no-preference) {
   .App-logo {
-    animation: App-logo-float infinite 3s ease-in-out;
+    animation: App-logo-spin infinite 20s linear;
   }
 }
 
 .App-header {
+  background-color: #282c34;
   min-height: 100vh;
   display: flex;
   flex-direction: column;
   align-items: center;
   justify-content: center;
   font-size: calc(10px + 2vmin);
+  color: white;
 }
 
 .App-link {
-  color: rgb(112, 76, 182);
+  color: #61dafb;
 }
 
-@keyframes App-logo-float {
-  0% {
-    transform: translateY(0);
+@keyframes App-logo-spin {
+  from {
+    transform: rotate(0deg);
   }
-  50% {
-    transform: translateY(10px);
-  }
-  100% {
-    transform: translateY(0px);
+  to {
+    transform: rotate(360deg);
   }
 }

+ 14 - 0
15_React/day-6/code/learn-redux/src/Layout/index.css

@@ -0,0 +1,14 @@
+.layout {
+  display: flex;
+}
+
+.layout header {
+  width: 200px;
+  padding: 20px;
+
+  background-color: beige;
+}
+
+.layout main {
+  padding: 20px;
+}

+ 24 - 0
15_React/day-6/code/learn-redux/src/Layout/index.jsx

@@ -0,0 +1,24 @@
+import { Link, Outlet } from 'react-router-dom';
+import './index.css';
+
+export default function Layout() {
+  return (
+    <div className="layout">
+      <header>
+        <nav>
+          <ul>
+            <li>
+              <Link to="/">home</Link>
+            </li>
+            <li>
+              <Link to="/counter">计数器</Link>
+            </li>
+          </ul>
+        </nav>
+      </header>
+      <main>
+        <Outlet />
+      </main>
+    </div>
+  );
+}

+ 0 - 0
15_React/day-6/code/my-app/src/index.css → 15_React/day-6/code/learn-redux/src/index.css


+ 8 - 9
15_React/day-6/code/my-app/src/index.js → 15_React/day-6/code/learn-redux/src/index.js

@@ -1,18 +1,17 @@
 import React from 'react';
-import { createRoot } from 'react-dom/client';
-import { Provider } from 'react-redux';
-import { store } from './app/store';
-import App from './App';
-import reportWebVitals from './reportWebVitals';
+import ReactDOM from 'react-dom/client';
 import './index.css';
+import reportWebVitals from './reportWebVitals';
+import { RouterProvider } from 'react-router-dom';
+import router from './router';
+import { Provider } from 'react-redux';
+import store from './store';
 
-const container = document.getElementById('root');
-const root = createRoot(container);
-
+const root = ReactDOM.createRoot(document.getElementById('root'));
 root.render(
   <React.StrictMode>
     <Provider store={store}>
-      <App />
+      <RouterProvider router={router} />
     </Provider>
   </React.StrictMode>
 );

Файловите разлики са ограничени, защото са твърде много
+ 0 - 0
15_React/day-6/code/learn-redux/src/logo.svg


+ 7 - 0
15_React/day-6/code/learn-redux/src/pages/Counter.jsx

@@ -0,0 +1,7 @@
+export default function counter() {
+  return (
+    <div>
+      <h3>计数器</h3>
+    </div>
+  );
+}

+ 7 - 0
15_React/day-6/code/learn-redux/src/pages/Home.jsx

@@ -0,0 +1,7 @@
+export default function Home() {
+  return (
+    <div>
+      <h3>主页</h3>
+    </div>
+  );
+}

+ 0 - 0
15_React/day-6/code/my-app/src/reportWebVitals.js → 15_React/day-6/code/learn-redux/src/reportWebVitals.js


+ 32 - 0
15_React/day-6/code/learn-redux/src/router/index.js

@@ -0,0 +1,32 @@
+import { createBrowserRouter } from 'react-router-dom';
+import Layout from '../Layout';
+import { Suspense, lazy } from 'react';
+const Home = lazy(() => import('../pages/Home'));
+const Counter = lazy(() => import('../pages/Counter'));
+
+const router = createBrowserRouter([
+  {
+    path: '/',
+    element: <Layout />,
+    children: [
+      {
+        index: true,
+        element: (
+          <Suspense>
+            <Home />
+          </Suspense>
+        ),
+      },
+      {
+        path: '/counter',
+        element: (
+          <Suspense>
+            <Counter />
+          </Suspense>
+        ),
+      },
+    ],
+  },
+]);
+
+export default router;

+ 16 - 0
15_React/day-6/code/learn-redux/src/store/index.js

@@ -0,0 +1,16 @@
+import { configureStore } from '@reduxjs/toolkit';
+
+const reducer = (state, action) => {
+  return {
+    user: {
+      name: '郭郭',
+    },
+  };
+};
+
+const store = configureStore({
+  // reducer: {},
+  reducer,
+});
+
+export default store;

BIN
15_React/day-6/code/my-app/public/favicon.ico


BIN
15_React/day-6/code/my-app/public/logo192.png


BIN
15_React/day-6/code/my-app/public/logo512.png


+ 0 - 58
15_React/day-6/code/my-app/src/App.js

@@ -1,58 +0,0 @@
-import React from 'react';
-import logo from './logo.svg';
-import { Counter } from './features/counter/Counter';
-import './App.css';
-
-function App() {
-  return (
-    <div className="App">
-      <header className="App-header">
-        <img src={logo} className="App-logo" alt="logo" />
-        <Counter />
-        <p>
-          Edit <code>src/App.js</code> and save to reload.
-        </p>
-        <span>
-          <span>Learn </span>
-          <a
-            className="App-link"
-            href="https://reactjs.org/"
-            target="_blank"
-            rel="noopener noreferrer"
-          >
-            React
-          </a>
-          <span>, </span>
-          <a
-            className="App-link"
-            href="https://redux.js.org/"
-            target="_blank"
-            rel="noopener noreferrer"
-          >
-            Redux
-          </a>
-          <span>, </span>
-          <a
-            className="App-link"
-            href="https://redux-toolkit.js.org/"
-            target="_blank"
-            rel="noopener noreferrer"
-          >
-            Redux Toolkit
-          </a>
-          ,<span> and </span>
-          <a
-            className="App-link"
-            href="https://react-redux.js.org/"
-            target="_blank"
-            rel="noopener noreferrer"
-          >
-            React Redux
-          </a>
-        </span>
-      </header>
-    </div>
-  );
-}
-
-export default App;

+ 0 - 15
15_React/day-6/code/my-app/src/App.test.js

@@ -1,15 +0,0 @@
-import React from 'react';
-import { render } from '@testing-library/react';
-import { Provider } from 'react-redux';
-import { store } from './app/store';
-import App from './App';
-
-test('renders learn react link', () => {
-  const { getByText } = render(
-    <Provider store={store}>
-      <App />
-    </Provider>
-  );
-
-  expect(getByText(/learn/i)).toBeInTheDocument();
-});

+ 0 - 8
15_React/day-6/code/my-app/src/app/store.js

@@ -1,8 +0,0 @@
-import { configureStore } from '@reduxjs/toolkit';
-import counterReducer from '../features/counter/counterSlice';
-
-export const store = configureStore({
-  reducer: {
-    counter: counterReducer,
-  },
-});

+ 0 - 67
15_React/day-6/code/my-app/src/features/counter/Counter.js

@@ -1,67 +0,0 @@
-import React, { useState } from 'react';
-import { useSelector, useDispatch } from 'react-redux';
-import {
-  decrement,
-  increment,
-  incrementByAmount,
-  incrementAsync,
-  incrementIfOdd,
-  selectCount,
-} from './counterSlice';
-import styles from './Counter.module.css';
-
-export function Counter() {
-  const count = useSelector(selectCount);
-  const dispatch = useDispatch();
-  const [incrementAmount, setIncrementAmount] = useState('2');
-
-  const incrementValue = Number(incrementAmount) || 0;
-
-  return (
-    <div>
-      <div className={styles.row}>
-        <button
-          className={styles.button}
-          aria-label="Decrement value"
-          onClick={() => dispatch(decrement())}
-        >
-          -
-        </button>
-        <span className={styles.value}>{count}</span>
-        <button
-          className={styles.button}
-          aria-label="Increment value"
-          onClick={() => dispatch(increment())}
-        >
-          +
-        </button>
-      </div>
-      <div className={styles.row}>
-        <input
-          className={styles.textbox}
-          aria-label="Set increment amount"
-          value={incrementAmount}
-          onChange={(e) => setIncrementAmount(e.target.value)}
-        />
-        <button
-          className={styles.button}
-          onClick={() => dispatch(incrementByAmount(incrementValue))}
-        >
-          Add Amount
-        </button>
-        <button
-          className={styles.asyncButton}
-          onClick={() => dispatch(incrementAsync(incrementValue))}
-        >
-          Add Async
-        </button>
-        <button
-          className={styles.button}
-          onClick={() => dispatch(incrementIfOdd(incrementValue))}
-        >
-          Add If Odd
-        </button>
-      </div>
-    </div>
-  );
-}

+ 0 - 6
15_React/day-6/code/my-app/src/features/counter/counterAPI.js

@@ -1,6 +0,0 @@
-// A mock function to mimic making an async request for data
-export function fetchCount(amount = 1) {
-  return new Promise((resolve) =>
-    setTimeout(() => resolve({ data: amount }), 500)
-  );
-}

+ 0 - 73
15_React/day-6/code/my-app/src/features/counter/counterSlice.js

@@ -1,73 +0,0 @@
-import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
-import { fetchCount } from './counterAPI';
-
-const initialState = {
-  value: 0,
-  status: 'idle',
-};
-
-// The function below is called a thunk and allows us to perform async logic. It
-// can be dispatched like a regular action: `dispatch(incrementAsync(10))`. This
-// will call the thunk with the `dispatch` function as the first argument. Async
-// code can then be executed and other actions can be dispatched. Thunks are
-// typically used to make async requests.
-export const incrementAsync = createAsyncThunk(
-  'counter/fetchCount',
-  async (amount) => {
-    const response = await fetchCount(amount);
-    // The value we return becomes the `fulfilled` action payload
-    return response.data;
-  }
-);
-
-export const counterSlice = createSlice({
-  name: 'counter',
-  initialState,
-  // The `reducers` field lets us define reducers and generate associated actions
-  reducers: {
-    increment: (state) => {
-      // Redux Toolkit allows us to write "mutating" logic in reducers. It
-      // doesn't actually mutate the state because it uses the Immer library,
-      // which detects changes to a "draft state" and produces a brand new
-      // immutable state based off those changes
-      state.value += 1;
-    },
-    decrement: (state) => {
-      state.value -= 1;
-    },
-    // Use the PayloadAction type to declare the contents of `action.payload`
-    incrementByAmount: (state, action) => {
-      state.value += action.payload;
-    },
-  },
-  // The `extraReducers` field lets the slice handle actions defined elsewhere,
-  // including actions generated by createAsyncThunk or in other slices.
-  extraReducers: (builder) => {
-    builder
-      .addCase(incrementAsync.pending, (state) => {
-        state.status = 'loading';
-      })
-      .addCase(incrementAsync.fulfilled, (state, action) => {
-        state.status = 'idle';
-        state.value += action.payload;
-      });
-  },
-});
-
-export const { increment, decrement, incrementByAmount } = counterSlice.actions;
-
-// The function below is called a selector and allows us to select a value from
-// the state. Selectors can also be defined inline where they're used instead of
-// in the slice file. For example: `useSelector((state: RootState) => state.counter.value)`
-export const selectCount = (state) => state.counter.value;
-
-// We can also write thunks by hand, which may contain both sync and async logic.
-// Here's an example of conditionally dispatching actions based on current state.
-export const incrementIfOdd = (amount) => (dispatch, getState) => {
-  const currentValue = selectCount(getState());
-  if (currentValue % 2 === 1) {
-    dispatch(incrementByAmount(amount));
-  }
-};
-
-export default counterSlice.reducer;

+ 0 - 33
15_React/day-6/code/my-app/src/features/counter/counterSlice.spec.js

@@ -1,33 +0,0 @@
-import counterReducer, {
-  increment,
-  decrement,
-  incrementByAmount,
-} from './counterSlice';
-
-describe('counter reducer', () => {
-  const initialState = {
-    value: 3,
-    status: 'idle',
-  };
-  it('should handle initial state', () => {
-    expect(counterReducer(undefined, { type: 'unknown' })).toEqual({
-      value: 0,
-      status: 'idle',
-    });
-  });
-
-  it('should handle increment', () => {
-    const actual = counterReducer(initialState, increment());
-    expect(actual.value).toEqual(4);
-  });
-
-  it('should handle decrement', () => {
-    const actual = counterReducer(initialState, decrement());
-    expect(actual.value).toEqual(2);
-  });
-
-  it('should handle incrementByAmount', () => {
-    const actual = counterReducer(initialState, incrementByAmount(2));
-    expect(actual.value).toEqual(5);
-  });
-});

+ 0 - 1
15_React/day-6/code/my-app/src/logo.svg

@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><g fill="#764ABC"><path d="M65.6 65.4c2.9-.3 5.1-2.8 5-5.8-.1-3-2.6-5.4-5.6-5.4h-.2c-3.1.1-5.5 2.7-5.4 5.8.1 1.5.7 2.8 1.6 3.7-3.4 6.7-8.6 11.6-16.4 15.7-5.3 2.8-10.8 3.8-16.3 3.1-4.5-.6-8-2.6-10.2-5.9-3.2-4.9-3.5-10.2-.8-15.5 1.9-3.8 4.9-6.6 6.8-8-.4-1.3-1-3.5-1.3-5.1-14.5 10.5-13 24.7-8.6 31.4 3.3 5 10 8.1 17.4 8.1 2 0 4-.2 6-.7 12.8-2.5 22.5-10.1 28-21.4z"/><path d="M83.2 53c-7.6-8.9-18.8-13.8-31.6-13.8H50c-.9-1.8-2.8-3-4.9-3h-.2c-3.1.1-5.5 2.7-5.4 5.8.1 3 2.6 5.4 5.6 5.4h.2c2.2-.1 4.1-1.5 4.9-3.4H52c7.6 0 14.8 2.2 21.3 6.5 5 3.3 8.6 7.6 10.6 12.8 1.7 4.2 1.6 8.3-.2 11.8-2.8 5.3-7.5 8.2-13.7 8.2-4 0-7.8-1.2-9.8-2.1-1.1 1-3.1 2.6-4.5 3.6 4.3 2 8.7 3.1 12.9 3.1 9.6 0 16.7-5.3 19.4-10.6 2.9-5.8 2.7-15.8-4.8-24.3z"/><path d="M32.4 67.1c.1 3 2.6 5.4 5.6 5.4h.2c3.1-.1 5.5-2.7 5.4-5.8-.1-3-2.6-5.4-5.6-5.4h-.2c-.2 0-.5 0-.7.1-4.1-6.8-5.8-14.2-5.2-22.2.4-6 2.4-11.2 5.9-15.5 2.9-3.7 8.5-5.5 12.3-5.6 10.6-.2 15.1 13 15.4 18.3 1.3.3 3.5 1 5 1.5-1.2-16.2-11.2-24.6-20.8-24.6-9 0-17.3 6.5-20.6 16.1-4.6 12.8-1.6 25.1 4 34.8-.5.7-.8 1.8-.7 2.9z"/></g></svg>

+ 0 - 5
15_React/day-6/code/my-app/src/setupTests.js

@@ -1,5 +0,0 @@
-// jest-dom adds custom jest matchers for asserting on DOM nodes.
-// allows you to do things like:
-// expect(element).toHaveTextContent(/react/i)
-// learn more: https://github.com/testing-library/jest-dom
-import '@testing-library/jest-dom/extend-expect';

BIN
15_React/day-6/note/ReduxAsyncDataFlowDiagram-d97ff38a0f4da0f327163170ccc13e80.gif


Някои файлове не бяха показани, защото твърде много файлове са промени