Allow the application to block navigations within the SPA and present the user a confirmation dialog to confirm the navigation. Mostly used to avoid using half-filled form data. This does not handle hard-reloads or cross-origin navigations.
The Blocker object returned by the hook has the following properties:
state unblocked - the blocker is idle and has not prevented any navigationblocked - the blocker has prevented a navigationproceeding - the blocker is proceeding through from a blocked navigationlocation blocked state, this represents the Location to which we blocked a navigation. When in a proceeding state, this is the location being navigated to after a blocker.proceed() call.proceed() blocked state, you may call blocker.proceed() to proceed to the blocked location.reset() blocked state, you may call blocker.reset() to return the blocker to an unblocked state and leave the user at the current location.// Boolean version let blocker = useBlocker(value !== ""); // Function version let blocker = useBlocker( ({ currentLocation, nextLocation, historyAction }) => value !== "" && currentLocation.pathname !== nextLocation.pathname ); function useBlocker(shouldBlock: boolean | BlockerFunction): Blocker Either a boolean or a function returning a boolean which indicates whether the navigation should be blocked. The function format receives a single object parameter containing the currentLocation, nextLocation, and historyAction of the potential navigation.
A Blocker object with state and reset functionality
import { useCallback, useState } from "react"; import { BlockerFunction, useBlocker } from "react-router"; export function ImportantForm() { const [value, setValue] = useState(""); const shouldBlock = useCallback<BlockerFunction>( () => value !== "", [value] ); const blocker = useBlocker(shouldBlock); return ( <form onSubmit={(e) => { e.preventDefault(); setValue(""); if (blocker.state === "blocked") { blocker.proceed(); } }} > <input name="data" value={value} onChange={(e) => setValue(e.target.value)} /> <button type="submit">Save</button> {blocker.state === "blocked" ? ( <> <p style={{ color: "red" }}> Blocked the last navigation to </p> <button type="button" onClick={() => blocker.proceed()} > Let me through </button> <button type="button" onClick={() => blocker.reset()} > Keep me here </button> </> ) : blocker.state === "proceeding" ? ( <p style={{ color: "orange" }}> Proceeding through blocked navigation </p> ) : ( <p style={{ color: "green" }}> Blocker is currently unblocked </p> )} </form> ); }