React applications often require navigation between different components and pages. The useHistory hook, provided by React Router, simplifies navigation by providing access to the browser’s history object. In this blog, we’ll explore the useHistory hook, understand its implementation, and see practical examples of how it enhances navigation in React applications.
Understanding useHistory
The useHistory hook is part of the React Router library, specifically designed for handling navigation in React applications. It allows components to interact with the browser’s history object, enabling programmatic navigation.
Importing useHistory:
To commence using useHistory for your React application, import it from react-router-dom:
import { useHistory } from "react-router-dom";
Accessing the History Object
Once imported, you can call useHistory() within your react component to get the history object:
const history = useHistory();
Here are some commonly used methods (or attributes) of the history object returned by useHistory and their purposes:
Navigation Methods
push(path, [state])
Logic
Push is used to navigate a new path by adding a new entry to the history stack. It allows you to provide an optional state object associated with the latest history entry.
Example
//JSX const history = useHistory(); history.push({ pathname: "/new-path", state: "New Page", });
The above example uses history.push to navigate to /new-path and passes the information provided in the state.
import React from "react"; import { useLocation } from "react-router-dom"; import Heading from "../components/useHistory/Heading"; const New = () => { const location = useLocation(); let data = location.state; return ( <div> <Heading>{data}</Heading> </div> ); }; export default New;
In the above example, when the user arrives at /new-path, you can access the passed state (New page) through the location object. If you’re using functional components, you can access them via the useLocation hook from react-router-dom. To learn about the location, please check out my profile.
This method of passing state is beneficial for sending data across routes that don’t need to be part of the URL.
replace(path, [state])
Logic
You use the function to replace the current entry on the history stack with a new one. This is useful when updating the current path without adding a new history entry.
Example
//JSX const history = useHistory(); history.replace({ pathname: "/updated-path", state: "Update Page", });
import React from "react"; import { useLocation } from "react-router-dom"; import Heading from "../components/useHistory/Heading"; const Update = () => { const location = useLocation(); let data = location.state; return <Heading>{data}</Heading>; }; export default Update;
In this example, the ClickHandler triggers history.replace instead of history.push to navigate to /details-page and pass state information in the state. history.replace overwrites the current history entry, eliminating the ability to return to it while history.push adds a new entry, allowing back navigation.
goBack()
Logic
GoBack simulates clicking the back button in the browser. It navigates back one step in the browser’s history.
Example
const goBackInHistory = () => { history.goBack(); };
When the button is clicked, clickHandler triggers history.goBack(), simulating the user returning to the browser’s history.
goForward()
Logic
GoForward simulates clicking the forward button in the browser. It navigates forward one step in the browser’s history.
Example
const goForwardInHistory = () => { history.goForward(); };
When the button is clicked, clickHandler triggers history.goForward(), simulating the user going forward in the browser’s history.
go(n)
Logic
The go function in JavaScript lets you navigate forwards or backward in the browser’s history by specifying a positive or negative number of steps.
Example
const goTwoStepsForward = () => { history.go(2); };
When the button is clicked, clickHandler triggers history.go(2), moving two steps forward in the browser’s history.
block
Logic
The history.block function in React Router shows users a confirmation dialog when they try to leave the current page. This feature helps prevent users from accidentally navigating away from a page without saving important information or changes.
Example
import React from "react"; import { useEffect } from "react"; import { useHistory } from "react-router-dom"; import Heading from "../components/useHistory/Heading"; function Block() { const history = useHistory(); useEffect(() => { const unblock = history.block( "Are you sure you want to leave this page? Your changes may not be saved." ); return () => { unblock(); }; }, [history]); return <Heading>Block Page</Heading>; } export default Block;
const toBlockPath = () => { history.push("/block-path"); };
In this example, when the Block component is rendered, it is called history.block, and a message will be displayed to the user when they try to navigate away from the page. The Block function returns a function to unblock the navigation, which we clean up in the useEffect hook’s cleanup function to avoid memory leaks.
When the user clicks the “Save” button, the toBlockPath function is called, which saves the form data and then allows navigation to the /block-path page by calling history.push.
Additional Properties
length:
This property indicates the number of entries in the history stack.
Example
const numberOfEnteries = history.length
action
This property returns the current navigation action, such as ‘PUSH’, ‘REPLACE’, or ‘POP’.
Example
const currentAction = history.action;
Let’s combine all the methods we have seen and use them to create a React application to better understand them:
import React from "react"; import { useHistory } from "react-router-dom"; import "./NavigationDemo.css"; const NavigationDemo = () => { const history = useHistory(); const currentAction = history.action; const navigateToNewPath = () => { history.push({ pathname: "/new-path", state: "New Page", }); }; const replaceCurrentPath = () => { history.replace({ pathname: "/updated-path", state: "Update Page", }); }; const goBackInHistory = () => { history.goBack(); }; const goForwardInHistory = () => { history.goForward(); }; const goTwoStepsForward = () => { history.go(2); }; const toBlockPath = () => { history.push("/block-path"); }; return ( <div className="container"> <h1>React Router Navigation Demo</h1> <button onClick={navigateToNewPath}>Navigate to New Path</button> <button onClick={replaceCurrentPath}>Replace Current Path</button> <button onClick={goBackInHistory}>Go Back</button> <button onClick={goForwardInHistory}>Go Forward</button> <button onClick={goTwoStepsForward}>Go Two Steps Forward</button> <button onClick={toBlockPath}>save</button> <button>{currentAction}</button> <p>Number of Entries in History: {history.length}</p> <p>Current Action: {history.action}</p> </div> ); }; export default NavigationDemo;
Output
Conclusion
Incorporating the useHistory hook into your React components enables dynamic and navigable user interfaces. Whether you’re adding new entries, updating existing pathways, or moving back and forth across history, useHistory’s functionalities enable developers to create seamless and engaging user experiences.