diff --git a/README.md b/README.md
index aba1d63..446e0f9 100644
--- a/README.md
+++ b/README.md
@@ -14,6 +14,8 @@ Check out the different branches to see how this repo evolved over a week of Rea
- (main) React components & props
- (react-state) React state with useState & useEffect
+- (react-lifting-state) React lifting state
+- (react-router) Reacter router
You can see the changes from day to day in the ["Pull Requests"](https://github.com/TechmongersNL/fs04-react/pulls) in this repo
diff --git a/package-lock.json b/package-lock.json
index 8e7ff14..7e493da 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -14,6 +14,7 @@
"axios": "^1.6.5",
"react": "^18.2.0",
"react-dom": "^18.2.0",
+ "react-router-dom": "^6.21.3",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4"
}
@@ -3353,6 +3354,14 @@
}
}
},
+ "node_modules/@remix-run/router": {
+ "version": "1.14.2",
+ "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.14.2.tgz",
+ "integrity": "sha512-ACXpdMM9hmKZww21yEqWwiLws/UPLhNKvimN8RrYSqPSvB3ov7sLvAcfvaxePeLvccTQKGdkDIhLYApZVDFuKg==",
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
"node_modules/@rollup/plugin-babel": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz",
@@ -14937,6 +14946,36 @@
"node": ">=0.10.0"
}
},
+ "node_modules/react-router": {
+ "version": "6.21.3",
+ "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.21.3.tgz",
+ "integrity": "sha512-a0H638ZXULv1OdkmiK6s6itNhoy33ywxmUFT/xtSoVyf9VnC7n7+VT4LjVzdIHSaF5TIh9ylUgxMXksHTgGrKg==",
+ "dependencies": {
+ "@remix-run/router": "1.14.2"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.8"
+ }
+ },
+ "node_modules/react-router-dom": {
+ "version": "6.21.3",
+ "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.21.3.tgz",
+ "integrity": "sha512-kNzubk7n4YHSrErzjLK72j0B5i969GsuCGazRl3G6j1zqZBLjuSlYBdVdkDOgzGdPIffUOc9nmgiadTEVoq91g==",
+ "dependencies": {
+ "@remix-run/router": "1.14.2",
+ "react-router": "6.21.3"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.8",
+ "react-dom": ">=16.8"
+ }
+ },
"node_modules/react-scripts": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz",
diff --git a/package.json b/package.json
index 906fb59..3e6ba3a 100644
--- a/package.json
+++ b/package.json
@@ -9,6 +9,7 @@
"axios": "^1.6.5",
"react": "^18.2.0",
"react-dom": "^18.2.0",
+ "react-router-dom": "^6.21.3",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4"
},
diff --git a/src/App.css b/src/App.css
index 74b5e05..7dc8026 100644
--- a/src/App.css
+++ b/src/App.css
@@ -36,3 +36,7 @@
transform: rotate(360deg);
}
}
+
+.background-blue {
+ background-color: rgb(232, 241, 244);
+}
diff --git a/src/App.js b/src/App.js
index 358e3b6..925c682 100644
--- a/src/App.js
+++ b/src/App.js
@@ -1,14 +1,27 @@
import "./App.css";
-import CharacterList from "./components/character-list";
+import CharacterListPage from "./pages/character-list-page";
+import { Route, Routes } from "react-router-dom";
+import HomePage from "./pages/home-page";
+import CharacterDetailPage from "./pages/character-detail-page";
// import something from 'some place'
// App.js is the entry point to the rest of your app
+// You can see how this behavior is set up in src/index.js
// This is default behavior for create-react-app
function App() {
return (
- {/* Now have a new CharactersList component, to keep our App component more clean and organized */}
-
+
+ Here is a header that appears above every page
+
+
+ } />
+ } />
+ } />
+
+
+ Here is a footer that appears below every page
+
);
}
diff --git a/src/components/character.js b/src/components/character.js
index 45572ed..cd53c4c 100644
--- a/src/components/character.js
+++ b/src/components/character.js
@@ -1,6 +1,7 @@
// You can import other components and use them too!
import Counter from "./counter";
import Image from "./image";
+import { Link } from "react-router-dom";
// A React component is just a function that returns some JSX
// Specifically, it returns some JSX with only one parent element
@@ -14,12 +15,6 @@ const Character = (props) => {
return (
<>
{props.name}
-
Blood type
-
{props.blood}
-
Birthday
-
{props.birthday}
-
Quote
-
{props.quote}
{/* using a component within a component also works! */}
{/* Passing props from CharacterList even further down into Counter */}
@@ -28,6 +23,14 @@ const Character = (props) => {
increaseLikes={props.increaseLikes}
id={props.id}
/>
+ {/* Link to /characters/1 if we're looking at Luna with id 1 */}
+ {/* Link to /characters/2 if we're looking at the second character with id 2 */}
+ {/* ...etc */}
+ {/* Then this will get matched to a Route defined in App.js */}
+ {/* You should never have a colon (:) in your Link "to" */}
+
+ Go to {props.name}'s detail page
+
>
);
diff --git a/src/components/counter.js b/src/components/counter.js
index b5181f6..8b817d7 100644
--- a/src/components/counter.js
+++ b/src/components/counter.js
@@ -24,7 +24,6 @@ const Counter = (props) => {
>
Increase likes
-
diff --git a/src/index.js b/src/index.js
index d563c0f..b390529 100644
--- a/src/index.js
+++ b/src/index.js
@@ -1,13 +1,16 @@
-import React from 'react';
-import ReactDOM from 'react-dom/client';
-import './index.css';
-import App from './App';
-import reportWebVitals from './reportWebVitals';
+import React from "react";
+import ReactDOM from "react-dom/client";
+import "./index.css";
+import App from "./App";
+import reportWebVitals from "./reportWebVitals";
+import { BrowserRouter } from "react-router-dom";
-const root = ReactDOM.createRoot(document.getElementById('root'));
+const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
-
+
+
+
);
diff --git a/src/pages/character-detail-page.js b/src/pages/character-detail-page.js
new file mode 100644
index 0000000..3bf3c22
--- /dev/null
+++ b/src/pages/character-detail-page.js
@@ -0,0 +1,47 @@
+import { useParams } from "react-router-dom";
+import axios from "axios";
+import { useEffect, useState } from "react";
+import { Link } from "react-router-dom";
+
+const CharacterDetailPage = () => {
+ // Get the value out of the path
+ // The useParams hook will get the variable named in your Route in your App.js
+ // useParams will that path variable in an object that we save into our own params variable
+ // I expect this to be the id of the character whose details we want to see
+ const params = useParams();
+ console.log(params);
+
+ const [characterDetailInfo, setCharacterDetailInfo] = useState(null);
+
+ // Get the characters detail data from the API
+ // Use the params object from above to get details for one specific character
+ const getCharacterDetail = async () => {
+ const response = await axios.get(
+ `https://my-json-server.typicode.com/TechmongersNL/fs03-react/characters/${params.id}`
+ );
+
+ console.log("response:", response.data);
+ setCharacterDetailInfo(response.data);
+ };
+
+ useEffect(() => {
+ getCharacterDetail();
+ }, []);
+
+ return characterDetailInfo ? (
+