<info 340/>
React Router
Joel Ross
Spring 2023
View of the Day
-
React Libraries (react-bootstrap)
-
Single Page Applications (lecture)
-
React Router (code demo)
-
URL Parameters (lecture + code demo)
-
Firebase Hosting (demo)
Project Draft 2
What we are looking for: Refactored Draft 1 into a React App
Converted the HTML/CSS from draft 1 into a published React app. Began to add interactive functionality.
- App is built: Ran create-react-app, etc. See assignment for details
- ~90% of content rendered: "most" of your app should be there (main page at least, Components for everything else)
- Has Components w/ props and data: Organize your Components! Can hard-code sample data for now
- Has 1 feature almost implemented: Includes event handling and state manipulation
- Fixes issues from draft 1: You're revising the HTML/CSS, fix problems while you're at it!
-
Published to Firebase hosting: get that working this draft
(see assignment for details; demo today!)
React Libraries
React components are structured to be self-contained, re-usable elements... so there are lots of pre-defined components online you can use!
In order to use a component in your app:
- Find it! (via npm, google, etc). Read the documentation
- Install it!
npm install lib-name
- Import it!
import { ComponentName } from 'lib-name'
- (import structure may vary per library)
- Render it!
<ComponentName />
- Remember to pass any expected props!
Single-Page Applications
Our chat app so far...
Client-Side Routing
Render a different component depending on the URL.
"IF the current url MATCHES a route, render this Component!"
function App(props) {
//pick a component based on the URL
let componentToRender = null;
if(currentUrl === '/home'){ //pseudocode comparison with URL
componentToRender = <HomePage />;
}
else if(currentUrl === '/about'){
componentToRender = <AboutPage />;
}
//render that component
return <div>{componentToRender}</div>;
}
react-router
A library of React Components that can determine which other components to render based on the current URL.
Install Library
Import Components
//in App.js
import { Routes, Route } from 'react-router-dom';
# Install library (on command line)
npm install react-router-dom
as of Nov 2021
Router Versions
The version we're targeting:
Adds data apis (not using)
BrowserRouter
The BrowserRouter component will keep track of the current URL in its state, and re-renders descendent components if that changes.
//index.js
import { BrowserRouter } from 'react-router-dom'
import App from './components/App.js'
//render the App *inside* of the BrowserRouter
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<BrowserRouter>
<App />
</BrowserRouter>
);
Routes
Pass elements in a Route Component to specify that they should only render when the URL matches a particular path. All routes go inside of a Routes element, which chooses which to "match" based on the URL
function App(props) {
return (
<Routes> {/* the collection of routes to match */}
{/* if currentUrlPath === "home" */}
<Route path="home" element={<HomePage />} />
{/* if currentUrlPath === "about" */}
<Route path="about" element={<AboutPage />} />
</Routes>
);
}
Links
Use a Link element (in place of an <a>) to create state-based links between routes.
function Nav() {
return (
<nav>
<ul>
<li>
{/* replaces anchor element */}
<Link to="home">Home</Link>
</li>
<li>
<Link to="about">About</Link>
</li>
</ul>
</nav>
);
}
Nesting Routes
The Route path corresponds to a segment of a URL, with nested Route elements corresponding to each segment. Nested Routes will render in place of an Outlet component
function App(props) {
return (
<Routes>
<Route path="user" element={<UserLayout />} >
<Route path="profile" element={<UserProfile />} />
<Route path="favorites" element={<FavoriteItems />} />
</Route>
<Route path="items" element={ <ItemList />} />
</Routes>
);
}
function UserLayout(props) {
render (
<div className="user-layout">
<h1>User Page</h1>
<Outlet /> {/* will be replaced with <UserProfile/>, etc */}
</div>
)
}
Protected Routes
A common use of nested routes is to make some routes protected, only showing content if e.g., the user is logged in.
function RequireAuth(props) {
//...determine if user is logged in
if(!userIsLoggedIn) { //if no user, say so
return <p>Forbidden!</p>
}
else { //otherwise, show the child route content
return <Outlet />
}
}
function App(props) {
return (
<Routes>
{/* protected routes */}
<Route element={<RequireAuth />}>
<Route path="profile" element={<ProfilePage />} />
<Route path="secret" element={<SecretPage />} />
</Route>
{/* public routes */}
<Route path="signin" element={<SignInPage />} />
</Routes>
)
}
protocol
domain
resource
"Hi Wikipedia, I'd like you to send me the Informatics page!"
two
t
(how to handle info)
(who has info)
(what info you want)
Web Server
Response
Using the Internet
Request
Uniform Resource Indicator
http://www.domain.com/users
=> a list of users
-
The address is the identifier, the list is the resource
HTTP requests are sent to a particular resource on the web, identified by its URI (think: web address).
URI Format
Like postal addresses, URIs follow a particular format.
-
scheme (protocol)
how to access the information -
domain
which web service has the resource -
path
what resource to access -
query
extra parameters (arguments) to the request
format:
?key=value&key=value&key=value
Many web services allow you to access their data through their web API.
E.g., GitHub! (https://docs.github.com/en/rest)
https://api.github.com/users/your-github-name/repos
# command-line downloading
curl https://api.github.com/users/info201/repos
# authenticate (to see private repos)
curl -u username https://api.github.com/repos/info201/repos
# include headers
curl -i https://api.github.com/users/info201/repos
Example URIs (API)
Example URIs (API)
A web service's URI has two parts:
-
The Base URI
- The EndPoint (e.g., path)
https://api.github.com
/users/{username}/repos
/repos/:owner/:repo
/emojis
A variable (also
:username
)
URL Params
Use :param syntax in the path to specify URL parameters. The useParams() hook lets you access the value of those parameters in the rendered element.
function App(props) {
return (
<Routes>
{/* if currentUrl == "posts/______" */}
{/* the string in the "blank" portion will be the
* `postId` param */}
<Route path="posts/:postId" element={<BlogPost />} />
</Routes>
);
}
import { useParams } from 'react-router-dom';
function BlogPost(props) {
const urlParams = useParams(); //access the URL params as an object
const postId = urlParams.postId; //can use destructuring instead
return (
{/* postId was the URL parameter from above! */}
<h1>You are looking at blog post {urlParams.postId}</h1>
)
}
Hosting on Firebase
GitHub pages is not able to cleanly handle client-side routing, so we'll use Firebase to host your projects instead!
Firebase is a web backend solution; it provides multiple features which you can access without need to "code" them yourselves.
- Web Hosting
- Databases
- User Authentication
next weeks
React Deployment to Firebase
Use a combination of firebase command line tools and create-react-app scripts to build and deploy your React application to Firebase hosting!
Action Items!
-
Project Draft 2 due SUNDAY!!
-
Review Ch 17: React Router
-
Read Ch 18: AJAX Requests
-
(we'll apply to React in lecture)
-
-
Problem Set 08 due Wednesday (it's small)
-
Problem Set 09 due Week 10 (it's small)
Next time: Working with Data: AJAX
info340sp23-router
By Joel Ross
info340sp23-router
- 237