Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

React nested routes #2

Open
wants to merge 14 commits into
base: main
Choose a base branch
from
47 changes: 47 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
"@testing-library/user-event": "^13.5.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",

"react-router-dom": "^6.21.1",

"react-scripts": "5.0.1",
"web-vitals": "^2.1.4"
},
Expand Down
7 changes: 7 additions & 0 deletions src/About.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import React from 'react';

function About() {
return <p>About</p>;
}

export default About;
79 changes: 60 additions & 19 deletions src/App.js
Original file line number Diff line number Diff line change
@@ -1,25 +1,66 @@
import logo from './logo.svg';
import './App.css';
import React from "react";
import {
BrowserRouter as Router,
Link,

} from "react-router-dom";
import BackButton from "./BackButton";
import ForwardButton from "./ForwardButton";
import GoHomeButton from "./GoHomeButton";
import RootRoutes from "./RootRoutes";

Route,
Routes,
} from "react-router-dom";
import NoMatch from "./NoMatch";

function Home() {
return <p>Home</p>;
}

function About() {
return <p>About</p>;
}



function App() {
const userId = [1, 2, 3, 4, 5];

return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
<Router>
<div className="App">

<BackButton />
<ForwardButton />

<GoHomeButton />

<Link to="/about">About</Link>
<br />

<h1>Navbar</h1>
{
userId.map((id) => (
<div key={id}>
<Link to={`/user/${id}`}>User {id}</Link>
</div>
))}

<RootRoutes />

<Link to="/">Home</Link>
<br />
<br />
<Link to="/about">About</Link>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="*" element={<NoMatch />} />
</Routes>

</div>
</Router>
);
}

export default App;
13 changes: 13 additions & 0 deletions src/BackButton.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import React from "react";
import { useNavigate } from "react-router-dom";

function BackButton() {
const navigate = useNavigate();
return (
<button type="button" onClick={() => navigate(-1)}>
Go Back
</button>
);
}

export default BackButton;
13 changes: 13 additions & 0 deletions src/ForwardButton.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import React from "react";
import { useNavigate } from "react-router-dom";

function ForwardButton() {
const navigate = useNavigate();
return (
<button type="button" onClick={() => navigate(1)}>
Go Forward
</button>
);
}

export default ForwardButton;
8 changes: 8 additions & 0 deletions src/GoHomeButton.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import React from "react";
import { Link } from "react-router-dom";

function GoHomeButton() {
return <Link to={"/"}>Go Home</Link>;
}

export default GoHomeButton;
7 changes: 7 additions & 0 deletions src/Home.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import React from 'react';

function Home() {
return <p>Home</p>;
}

export default Home;
16 changes: 16 additions & 0 deletions src/NoMatch.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { useLocation } from "react-router-dom";

function NoMatch() {
const location = useLocation();

return (
<h3>
No match for <code>{location.pathname}</code>
</h3>
);
}


export default NoMatch;


24 changes: 24 additions & 0 deletions src/RootRoutes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import React from 'react'
import { BrowserRouter as Router, Routes, Route, Link } from "react-router-dom";
import Home from "./Home";
import About from "./About";
import User from './User';
import NoMatch from './NoMatch';

function RootRoutes() {
return (

<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/users/:userId" element={<User />}>
<Route path="posts" element={<p>Here are a list of the user’s posts</p>} />
<Route path="posts/:postId" element={<p>Here is a single post</p>} />
</Route>
<Route path="*" element={<NoMatch />} />
</Routes>

)
}

export default RootRoutes;
20 changes: 20 additions & 0 deletions src/User.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React from 'react'
import UserProfile from './UserProfile';
import { Outlet, Link, useParams } from 'react-router-dom';

function User() {
const { userId } = useParams();

return (
<>
<UserProfile />
<hr/>
<Link to={`/users/${userId}/posts`}>View All Posts</Link>
||
<Link to={`/users/${userId}/posts/1`}>View Post with ID 1</Link>
<hr/>
<Outlet />
</>
)
}
export default User
32 changes: 32 additions & 0 deletions src/UserProfile.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import React, { useEffect, useState } from "react";
import { useParams } from "react-router-dom"; // added this import

function UserProfile() {
const [user, setUser] = useState({});
const { userId } = useParams(); // Correctly extracting 'userId' from the URI


useEffect(() => {
async function loadUser() {
const response = await fetch(
`https://jsonplaceholder.typicode.com/users/${userId}`
);
const userFromAPI = await response.json();
setUser(userFromAPI);
}
loadUser();
}, [userId]);

// No need to change anything below here
if (user.id) {
return Object.entries(user).map(([key, value]) => (
<div key={key}>
<label>{key}</label>: {JSON.stringify(value)}
<hr />
</div>
));
}
return "Loading...";
}

export default UserProfile;