Section 1

Learning Objectives
Students Will Be Able To: |
---|
Add user State to the MERN-Stack App |
Selectively Render Components Using a Ternary Expression |
Implement Client-Side Routing Using the React Router Library |
Implement Basic Navigation in a MERN-Stack App |
Road Map
- The Plan - Part 2
- MERN-Infrastructure
- The Lab
- Further Study
The Plan - Part 2
In Part 2 we will implement client-side routing as we continue to learn how to build a MERN-Stack app by following a realistic workflow.
Part 2 - Client-Side Routing:
- Ensuring that the React Dev Server Sends AJAX Calls to the Express Server
- Set up
user
state - Add skeleton page-level components
- Conditionally render based on the
user
state - Intro client-side routing using React Router
- Implement client-side routing
- Implement a typical navigation bar
Ensuring that the React Dev Server Sends AJAX Calls to the Express Server
❓ Which host/server will that fetch request be sent to?
The same host as shown in the address bar: localhost:3000
❓ Where do we actually need the fetch requests be sent to during development?
Our Express server that's listening for AJAX requests at localhost:3001
!
BTW, this is only a problem during development - the deployed app will be just fine thanks to our chosen MERN-Stack structure that uses a single project for the frontend and backend.
Luckily, the React team has created an easy fix for this dilemma. The React development server allows us to configure a "proxy" which specifies the host to forward API/AJAX calls to.
The fix is to add a "proxy"
key in the TOP-LEVEL of the package.json:
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"proxy": "http://localhost:3001"
}
Note: The React dev server will NOT automatically restart when changes are made to the package.json file.
1. Set Up user
State
Before we jump into the routing, let's set up some state that we can use to dynamically render different components depending upon two factors:
- Is there a logged in user?
- If the user is logged in, render different page-level components according to the path in the address bar.
The following diagrams the routing in MERN CAFE:

Note that <App>
is always rendered but only one of the other page-level components render.
Is There a Logged In User?
A good place to start is to define the user
state.
💪 Practice Exercise - Define the user
State in App.jsx (2 minutes)
- Use the
useState
hook to define a state variable nameduser
. - Initialize
user
tonull
. - The setter function should be named according to convention.
Hint: Don't forget to add the necessary import.
2. Add Skeleton Page-Level Components
Now that we have the user
state, let's continue setting up routing by stubbing up those three page-level components above.
❓ In which folder will we define these new page-level components?
src/pages
💪 Practice Exercise - Stub up MERN CAFE's page-level components (5 minutes)
- Create the
<AuthPage>
,<NewOrderPage>
and<OrderHistoryPage>
components. - Be sure to follow best practices (each in their own folder, etc.) and naming conventions.
- Each component should simply render an
<h1>
with the name of the component as its content, e.g.,<h1>AuthPage</h1>
.
Hint: Be productive by defining one component, then copy/paste its folder and rename everything.
3. Conditionally Render Based On the user
State
We've already seen how to conditionally render components by using:
- Ternary expressions: Used to render one component or another.
- Logical (
&&
) expressions: Used to render a component or nothing.
Examining our routing diagram above, we can see that we are conditionally rendering based upon whether the state of user
is null
(user not logged in) or not null
(user logged in).
Since we want to render either <AuthPage>
or one of the other two (<NewOrderPage>
or <OrderHistoryPage>
), we'll opt for a ___ expression.
Until we start using React Router, we'll just render <NewOrderPage>
if there's a user logged in.
Here's the refactor in App.jsx:
return (
<main className="App">
{ user ?
<NewOrderPage />
:
<AuthPage />
}
</main>
);
You'll have an error if the components were not automatically imported. Let's ensure all three components are imported while we're at it:
import './App.css';
// Import the following components
import AuthPage from '../AuthPage/AuthPage';
import NewOrderPage from '../NewOrderPage/NewOrderPage';
import OrderHistoryPage from '../OrderHistoryPage/OrderHistoryPage';
Tip:
command + D
comes in handy for using multiple cursors to edit.
After the imports we're rendering the <AuthPage>
as expected.

Updating the hook's State to any truthy value will result in <NewOrderPage>
rendering instead!
Now let's learn about how we can use React Router to perform client-side routing...
4. Intro to Client-Side Routing Using React Router
The React library does not include routing functionality.
React Router is the de facto client-side routing library for both React and React Native.
React Router has recently been updated from version 5.x to 6.x which included breaking changes. Be aware that the code in most of the tutorials, etc. out there that include React Router may not work any more.
Install React Router
Since it's a third-party library, React Router must be installed:
npm i react-router-dom
react-router-dom
is the web-based router used with React apps.react-router-native
is the library for React Native.
How it Works - React Router Is Component-Based!
React Router provides several components used to conditionally render our app's components based upon the path of the URL in the address bar
Please read the above again because it's fundamental to understanding how React Router works.
The <BrowserRouter>
Component
<BrowserRouter>
is the top-level React Router component that makes React Router work.
Only a single <BrowserRouter>
needs to be rendered and any components that need to use routing features must be nested within it, thus, the convention is to wrap the <App>
component.
❓ In which module will we need to wrap <App>
with <BrowserRouter>
?
index.js
Check out how we can use an alias with the as
keyword when importing:
import App from './pages/App/App';
// Import the top-level BrowserRouter component
import { BrowserRouter as Router } from 'react-router-dom';
Now let's refactor so that <App>
is rendered by <Router>
:
ReactDOM.render(
<React.StrictMode>
<Router><App /></Router>
</React.StrictMode>,
document.getElementById('root')
);
Using React Developer Tools we can see that the <BrowserRouter>
component renders a few other components then our <App>
component:

Note: Those components named ending with
.Provider
are using React's Context API to provide info to components down in the component hierarchy without having to pass that info as props.
5. Implement Client-Side Routing
Because React Router is component-based, it can be used in any component to conditionally render other components.
However, most React apps only need to perform routing in the <App>
component - let's see how...
The <Routes>
Component
Any component that needs to define client-side routes will first need to render a <Routes>
component.
Because <App>
is where we will define all of our routes, let's import the Routes
component there:
import { useState } from 'react';
// Add the following import
import { Routes } from 'react-router-dom';
Now we can use <Routes>
in <App>
to wrap our future routes...
return (
<main className="App">
{ user ?
<Routes>
{/* Route components in here */}
</Routes>
:
<AuthPage />
}
</main>
);
On to defining specific routes using the <Route>
component...
The <Route>
Component
The <Route>
component is the main component used to conditionally render a component instance (referred to as an "element" by React Router).
<Route>
works by simply rendering the element (instance of a component) assigned to its element
prop when its path
prop matches the current URL (path) in the address bar!
Let's add the <Route>
component to our list imports:
import { useState } from 'react';
// Add the following import
import { Routes, Route } from 'react-router-dom';
Rendering Components According to the Path of the URL
Once again referring to the routing diagram for MERN CAFE shows that we want to render:
<NewOrderPage>
when we browse to/orders/new
, and<OrderHistoryPage>
when we browse to/orders
So, let's add a <Route>
component and set both its path
and element
prop to conditionally render <NewOrderPage>
:
return (
<main className="App">
{ user ?
<Routes>
<Route path="/orders/new" element={<NewOrderPage />} />
</Routes>
:
<AuthPage />
}
</main>
);
As you can see, we've set the path
prop to the URL/path that we plan to use for this route.
Additionally, the element
prop is interesting in that it accepts an actual component instance:
element={<NewOrderPage />}
vs. the previous way of providing the component itself:
component={NewOrderPage}
The advantage of the new approach is that it's easier to pass props to the component being rendered.
Temporarily Update user
State for Testing Purposes
To avoid having to continually update the user
state using React Developer Tools, let's temporarily initialize user
to an empty object instead of null
:
const [user, setUser] = useState({});
Now, thanks to the <Route>
component we just added, changing the path of the URL to /orders/new
will render the <NewOrderPage>
component as expected:

💪 Practice Exercise - Add Another <Route>
(2 minutes)
- Add a new
<Route>
used to render<OrderHistoryPage />
when the path of the URL is/orders
- Test by changing the path of the URL back and forth between
/orders
and/orders/new
.
6. Implement a Typical Navigation Bar
Although MERN CAFE does not utilize a typical navigation bar, we'll code one as part of the infrastructure since many MERN-Stack apps will utilize one.
💪 Practice Exercise - Stub up a <NavBar>
component (3 minutes)
- Create a
<NavBar>
component within thecomponents
folder. <NavBar>
should render a<nav>
React Element with the text "NavBar" as its only content for now.- Import
<NavBar>
in App.jsx
❓ Assuming we want <NavBar>
to always display when there's a logged in user and before the page-level component, where would we add it to the JSX?
Right before the <Routes>
, requiring a React Fragment to wrap <NavBar>
and <Routes>
.
Yup, just like this:
return (
<main className="App">
{ user ?
<>
<NavBar />
<Routes>
<Route path="/orders/new" element={<NewOrderPage />} />
<Route path="/orders" element={<OrderHistoryPage />} />
</Routes>
</>
:
<AuthPage />
}
</main>
);
Note the necessity to add a React.Fragment (
<>
) to wrap the<NavBar>
and<Routes>
components.
Resulting in this for now:

❓ Assuming we want <NavBar>
to render at all times regardless of whether there's a logged in user or not, where would we add it to the JSX?
Between <main>
and the ternary expression.
The <Link>
Component
❓ What HTML element did we use to change the URL in our previous web apps?
The <a>
hyperlink element.
❓ What would happen if we used traditional HTML hyperlinks in a SPA?
It would cause a page reload when performing the navigation.
Luckily, React Router provides a <Link>
component that renders hyperlinks that when clicked, change the URL client-side only without triggering an HTTP request.
Here's how we can use <Link>
components in NavBar.jsx to change the route client-side:
// Don't forget the import
import { Link } from 'react-router-dom';
export default function NavBar() {
return (
<nav>
<Link to="/orders">Order History</Link>
|
<Link to="/orders/new">New Order</Link>
</nav>
);
}
Clicking any of the links performs client-side routing where React Router will:
- Update the path in the address bar without causing the page to reload
- Automatically trigger a render

IMPORTANT: Inspecting the elements on the page will reveal that indeed an
<a>
element is being emitted to the DOM when we use a<Link>
component. However, although they look like ordinary<a>
elements, React intercepts their click event thus preventing an HTTP request from being sent. However, if you accidentally use an<a>
tag, React will not intercept the click event and a page reload will occur 😞
Although we've learned most there is to know about client-side routing, we will learn more in future lessons, including how to change client-side routes programmatically (via code).
Congrats on implementing client-side routing!
On to the lab!
Further Study
Route Params - Client-Side
- Check out React Router's
useParams
hook that allows you to access route parameters similar to how we did in Express.
Other Topics
- Use React Router's
<NavLink>
component when you want to style hyperlinks dynamically based upon the current URL. - Learn more about the Context API which is a way to provide info to child components without having to pass that info as props.