React Redirections for Single Page Applications

Jerry Brown
Nerd For Tech
Published in
4 min readApr 2, 2021

--

One of the biggest advantages of building single-page web applications is the ability to select updates for specific components on the page, rather than completely reloading a new page. Among other things, this removes the need for repeated server requests every time an action is taken which can significantly improve program speed.

Unfortunately, this increased speed comes at the cost of tracking browser history. When you click the browser’s back button in a single-page app, the browser only knows which page was last loaded, not the previous state of the application.

Enter react-router-dom

React Router provides a way to declare route navigation in a single-page app and link the route to render a component. This way, your program can replicate the experience of clicking on a link to view the contents of a different page while technically still remaining on the initially-loaded HTML file. Furthermore, the package allows you to specify a path that can be appended to the browser’s URL, completing the look of a standard click and redirect.

To get set up:

npm install react-router-dom

And declare your routes (taken from my latest project’s App.js):

import { BrowserRouter as Router, Route } from 'react-router-dom'
...
return (
<div className="App">
<Router>
<>
<NavbarContainer />
<Route exact path="/" component={CalendarContainer} />
<Route exact path="/tweets" component={TweetsContainer} />
<Route exact path="/discover" component={DiscoverContainer} />
<Route exact path="/new" component={EventFormContainer} />
</>
</Router>
</div>
);

Then inside the navbar component, you’ll want to import NavLink:

import { NavLink } from 'react-router-dom'

and specify the path for each link:

<NavLink to="/new">Add Event</NavLink>

Redirections

Now on to the fun part — how to redirect within a single-page web application. The main use case for redirecting in my program was after a user submits a form to create a new event, the application should redirect back to the homepage where they can view their newly created event.

Each <Route /> that is declared is automatically passed three render methods:

  1. match
  2. location
  3. history

We’ll focus on history to handle redirections. Here’s what this.props.history looks like when we render the EventFormContainer:

According to the documentation, push(path, [state]) (function) Pushes a new entry onto the history stack. In other words, we can push a path into the history object to simulate a redirection!

The initial implementation of this was to tack it onto the end of the handleSubmit callback function that gets triggered when the form is submitted.

handleSubmit = (e) => {
e.preventDefault()
this.props.createEvent(this.state)
this.props.history.push('/')
}

Awesome! We’re now redirecting after the form is submitted. However, this implementation will cause a redirection regardless of whether or not the data submitted in the form is valid. To ensure that the redirection happens only after a successful submission we’ll want to relocate this into our createEvent action:

export const createEvent = (history, event) => {
return (dispatch) => {
const configObj = {
method: "POST",
headers: {
"Content-Type": "application/json",
"Accepts": "application/json"
},
body: JSON.stringify(event)
}
fetch(url, configObj)
.then(res => res.json())
.then(data => {
dispatch({ type: 'ADD_EVENT', event: data })
history.push('/')
})
}
}

Updated handleSubmit callback:

handleSubmit = (e) => {
e.preventDefault()
this.props.createEvent(this.props.history, this.state)
}

Now, the page only redirects after it’s confirmed that our API post request was successful.

Nested Components

If the component that you’re trying to redirect from is nested, it won’t automatically receive the match, location, and history props. As an alternative to passing history down as a prop through many component layers, react-router-dom offers “withRouter” to access the history object’s properties.

Import withRouter into your nested component:

import {withRouter} from 'react-router-dom'

and then be sure to wrap the exported component:

export default withRouter(NestedComponent)

The component now has full access to the same history object, and can preform the same push onto the history stack without receiving history as props.

While there was only one obvious use for redirections within the current state of my program, it’s clear how useful this could be should the project expand into new features like user registrations, editing event details, etc.

You can check out the latest version of my NFT Drop Calendar here. Feel free to submit a new NFT Drop event and experience the magic of single-page redirecting!

--

--