SICT

BTI425

Web Programming for Apps and Services

Schedule Notes Resources MyApps Instructions Graded Work Code examples

“Routing” in React

One of the key components in creating a SPA (Single Page Application) is Routing. When Routing is implemented using a framework like React, we will find that we can browse different URL’s within our app without actually reloading the page. In this case, the components of one URL are swapped out for the components of another, giving the illusion that we’re navigating through multiple pages, when we’re really just adding / removing components based on the browser URL / history. Our user interface is in-sync with the URL.

The most widely-used routing library used to achieve this in React is: React Router:

Components are the heart of React’s powerful, declarative programming model. React Router is a collection of navigational components that compose declaratively with your application. Whether you want to have bookmarkable URLs for your web app or a composable way to navigate in React Native, React Router works wherever React is rendering.


Getting Started using React Router

To start using the React Router library in our web app, we must first fetch react-router-dom using npm (once we have halted our debugging server using Control+C):

npm install react-router-dom

Now, let’s say that we have 3 top-level components that represent 3 separate views, ie: Home, Projects and Project:

function Home(){
  return <h1>Home Page</h1>
}

function Projects(){
  return <h1>All Projects Page</h1>
}

function Project(){
  return <h1>Specific Project Page</h1>
}

Quick Note: Each of these components (views) currently only renders an <h1> element, however in a real application they would be defined in separate files and contain many child components.

If we wish to conditionally render each of the above components (views) based on the following routes:

We need to modify our App.js file as well as our index.js file.


index.js changes

FYI, if you have to work with old obsolete legacy browser versions: The above code specifies the type of router that we will be using in our <App /> component. This could be either <BrowserRouter> or <HashRouter>. The Hash Router technique is generally used to support legacy browsers and React “strongly recommend(s) you do not use HashRouter unless you absolutely have to.”


App.js changes

Import the <Route> and <Routes> components:

import { Route, Routes } from 'react-router-dom';

Import the <Home>, <Projects>, <Project> components:

import Home from './Home';
import Projects from './Projects';
import Project from './Project';

Update the return value of the “App” function to use the following JSX:

<Routes>
  <Route path='/' element={<Home />} />
  <Route path='/Projects' element={<Projects />} />
  <Route path='/Project' element={<Project />} />
</Routes>

Here, we can define our routes explicitly using the “Routes” component with our three nested “Route” components. Each of the routes have a “path” property which we use to define the target route and an “element” property that we use to define the component (see: <Routes> & <Route> ).

NOTE: Components will only be added or removed as children of the <Routes></Routes> component, so if we wish to have parts of the UI that are consistent across all routes, we can place JSX above or below it, for example:

<header>Header</header>

<Routes>
  <Route path='/' element={<Home />} />
  <Route path='/Projects' element={<Projects />} />
  <Route path='/Project' element={<Project />} />
</Routes>

<footer>Footer</footer>


Adding URL Parameters to our Routes

If we wish to pass a specific URL parameter to a given route, we can use the same syntax as we’re accustomed to in Node.js, ie: “/routeName/:parameter”. To read the “:parameter” in the <Project /> component (so we can make use of routes like “/project/4”, etc), we need to make the following changes to our files:

Once we have made the above changes (pulled the parameter using useParams hook, etc.), we can now render routes that look like “/Project/9” or “/Project/abc” and see the results reflected in the browser.


Adding Query Parameters to our Routes

If we wish to obtain the query parameters for a specific route, the process is very similar, however the ability to actually parse the value(s) is absent from React Router so we require one extra step (below). To get started:

This will give us the full query string (using “location.search”). However, if we wish to parse the string and access individual parameters, we will need to make use of the native URLSearchParams, ie:

const urlParams = new URLSearchParams(location.search);

The ‘urlParams’ object can now be used to fetch individual query params, ie:

let page = urlParams.get("page"); // get the value of the "page" query parameter (NOTE: returns null if "page" was not found in the query string)


Adding A “Not Found” Route

Using React Router, we can easily define a “Not Found” route - this is analogous to the “404” error that we returned in our server.js files in WEB322 when a route was not matched.

To add a “Not Found” route, we simply need to add another route as a child to our <Routes> component defined in App.js. This route will simply match the path “*”, ie:

<Route path="*" element={<Notfound />} />


Linking to a Route

To use the react router effectively, we cannot simply use normal links to route to our pages from within the application. For example, using code like:

<a href="/myRoute">My Route</a>

would lead to a whole page reload (we only want to load the full app at the beginning, not after every route change). Instead, what we need to do is use the <Link> component (from “react-router-dom”), to prevent this from happening.

The same code can updated to use the <Link> component as follows:

<Link to='/myRoute'>My Route</Link>


“Redirecting” to a Route

Sometimes, we wish to “redirect” the user to a different route and override the current route in the “history” stack (or alternatively “push” it onto the current history stack) - this is similar to what we would use res.redirect() for in our Node.js servers.

React provides an intuitive way to achieve this, by providing a special <Navigate /> component. When rendered, it will redirect the client to the specified route using the following syntax:

<Navigate to="/newRoute" />

Additionally, we have the ability to programmatically change routes from within our code (for example, when an event occurs). This can be accomplished using the useNavigate hook from ‘react-router-dom’:

import { useNavigate } from "react-router-dom";

function HomeButton() {
  const navigate = useNavigate()

  function handleClick() {
    navigate("/home");
  }

  return (
    <button type="button" onClick={handleClick}>
      Go home
    </button>
  );
}