In the previous exercise you learned how to redirect declaratively by rendering a Redirect
component that updates the browser’s current location. Though this approach follows React Router’s declarative coding style, it does introduce a few extra steps in the React rendering lifecycle:
- The
Redirect
component must be returned - The
Redirect
is then rendered - The URL is then updated
- And finally the appropriate route is rendered.
React Router also provides a mechanism for updating the browser’s location imperatively: the Router
‘s history
object which is accessible via the useHistory()
hook.
import { useHistory } from 'react-router-dom';
The history
object that useHistory()
returns has a number of methods for imperatively redirecting users. The first and most straightforward is history.push(location)
which redirects the user to the provided location
.
Consider this example which immediately triggers a redirect back to the /
page after a user successfully submits a <form>
:
import { useHistory } from `react-router-dom` export const ExampleForm = () => { const history = useHistory() const handleSubmit = e => { e.preventDefault(); history.push('/') } return ( <form onSubmit={handleSubmit}> {/* form elements */ } </form> ) }
By enabling imperative updates to the browser location, the history
object allows you to respond immediately to user input without having to wait.
You might be wondering how the history
object works. Internally, the BrowserRouter
‘s history
object uses the html5 history API. In brief, browser history
is a stack that stores the URLs visited by the user and maintains a pointer to the user’s current location. This history
API allows you to navigate through a user’s session history and alter the history stack if necessary.
In addition to history.push()
, the history
object has a few more useful methods for navigating through the browser’s history:
history.goBack()
which navigates to the previous URL in the history stackhistory.goForward()
which navigates to the next URL in the history stackhistory.go(n)
which navigatesn
entries (where positiven
values are forward and negativen
values are backward) through the history stack
Below, we can see how the .goBack()
method is used to create a “Go Back” button:
import { useHistory } from `react-router-dom` export const BackButton = () => { const history = useHistory() return ( <button onClick={() => history.goBack()}> Go Back </button> ) }
Instructions
Task 1
So far, you may have noticed the “Back” and “Forward” buttons in the Footer
component. However, if you try clicking on them, nothing will happen. Let’s fix that using the history
object and its methods!
First, navigate to Footer.js and import the useHistory
hook.
Hint
Use the named import syntax to import the useHistory
method from 'react-router-dom'
:
import { value } from 'package-name';
Task 2
Next, inside the Footer
component, call useHistory()
to get the history
object.
Hint
Your code should look like this:
const history = useHistory();
Task 3
Finally, modify the goBack
and goForward
click handlers such that they imperatively redirect the user.
Verify your work by navigating to a few URLs and then using the “Back” and “Forward” buttons in the footer.
Hint
Call the history
object’s .goBack()
method inside the goBack
handler. Call the history
object’s .goForward()
method inside the goForward
handler.
Task 4
Lastly, let’s add an imperative redirect to the SignUp
component such that after a user submits their username they are redirected to the /profile
page.
Navigate to SignUp.js and import the useHistory
hook.
Then, use the appropriate history
method to redirect the user to '/profile'
at the end of the handleSubmit
method.
Test that your code works by signing up and ensuring that you are redirected to the profile page (which you can now view since loggedIn
is now true).
Hint
Import the useHistory
hook from react-router-dom
, call it to get a history
object, and use the history
object’s push
function to redirect the user to '/profile'
.