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.
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 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:
npm install lib-name
import { ComponentName } from 'lib-name'
<ComponentName />
react-router
A library of React Components that can determine which other components to render based on the current URL.
//in App.js
import { Routes, Route } from 'react-router-dom';
# Install library (on command line)
npm install react-router-dom
as of Nov 2021
The version we're using:
Adds data apis (not using)
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>
);
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>
);
}
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>
);
}
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>
)
}
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
Request
http://www.domain.com/users
=> a list of users
HTTP requests are sent to a particular resource on the web, identified by its URI (think: web address).
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
A web service's URI has two parts:
The Base URI
https://api.github.com
/users/{username}/repos
/repos/:owner/:repo
/emojis
A variable (also
:username
)
Use :param syntax in the path to specify URL parameters. The useParams() hook lets you access the value of those parameter in 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>
)
}
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.
after the holiday
Use a combination of firebase command line tools and create-react-app scripts to build and deploy your React application to Firebase hosting!
Project Draft 2 due Wednesday
Review Ch 17: React Router
Read Ch 18: AJAX Requests
(we'll apply to React in lecture)
Problem Set 08 due Monday (it's small)
Problem Set 09 due next week (it's small)
Next time: Working with Data: AJAX