react-router-navigation-prompt

repository·master·Indexed 41 days ago

https://github.com/zacharyrsmith/react-router-navigation-prompt

A replacement for the React Router <Prompt/> component that allows for custom UI dialogs and modals instead of browser-native alert boxes. Version 1.9.6 provides a render prop pattern to control navigation confirmation via isActive, onConfirm, and onCancel, with support for async cleanup through beforeConfirm and beforeCancel callbacks.

Tokens
2.5K
Snippets
3
Records
7
Agent score
51%

What's inside react-router-navigation-prompt

  1. Use NavigationPrompt for custom navigation dialogs

    master

    The <NavigationPrompt/> component is a replacement for the standard React Router <Prompt/>. While <Prompt/> is limited to browser-native alert boxes, <NavigationPrompt/> allows you to render custom UI (like modals or dialogs) to confirm navigation.

    Important Considerations:

    • Browser Security: For security reasons, browsers may still force a vanilla alert box for certain actions, such as reloading the page, closing the tab/window, or navigating away from the site entirely. In these cases, your custom UI might not be shown.
    • History Support: Currently, this component is tested with BrowserHistory. It has known issues with HashHistory.
    • Multiple Histories: Like the original React Router <Prompt/>, this component does not work with multiple BrowserHistory instances.
    • Function-based when prop: If you pass a function to when, ensure you check that nextLocation and action are defined before using them.
    import NavigationPrompt from "react-router-navigation-prompt";
    
    <NavigationPrompt when={this.state.shouldConfirmNavigation}>
      {({ onConfirm, onCancel }) => (
        <ConfirmNavigationModal
          when={true}
          onCancel={onCancel}
          onConfirm={onConfirm}
        />
      )}
    </NavigationPrompt>
  2. How NavigationPrompt works with render props

    master

    The NavigationPrompt component uses a render prop to expose the internal state of the prompt to your custom UI. When the when condition is met, the component enters an isActive state and renders its children.

    The Render Prop Object: Your child function receives an object with the following properties:

    • isActive: A boolean indicating if the navigation is currently being blocked and the prompt should be visible.
    • onConfirm: A function to call when the user decides to proceed with the navigation. This triggers the beforeConfirm logic and eventually calls history.push, history.replace, or history.goBack.
    • onCancel: A function to call when the user decides to stay on the current page. This resets the prompt state.
  3. Control navigation with onConfirm and onCancel

    master

    The NavigationPrompt render prop provides two primary functions to control the flow of navigation:

    • onCancel: Resets the prompt state and allows the user to stay on the current page. If beforeCancel is provided as a prop, it will be called first.
    • onConfirm: Proceeds with the navigation to the nextLocation. If beforeConfirm is provided as a prop, it will be called first. If the action was a 'POP' (back button), it will use history.goBack() if allowGoBack is enabled, otherwise it defaults to history.push to a default location (usually /).
  4. Implement complex navigation logic with NavigationPrompt

    master

    You can use a function for the when prop to trigger the prompt only under specific conditions, such as when the user is navigating to a path that does not start with the current path. You can also use beforeConfirm to run cleanup logic before the navigation proceeds.

    import NavigationPrompt from "react-router-navigation-prompt";
    import Modal from "./your-own-code";
    
    <NavigationPrompt
      beforeConfirm={(clb) => this.cleanup(clb)} // call the callback function when finished cleaning up
      renderIfNotActive={true}
      when={(crntLocation, nextLocation, _action) =>
        !nextLocation || !nextLocation.pathname.startsWith(crntLocation.pathname)
      }
    >
      {({ isActive, onCancel, onConfirm }) => {
        if (isActive) {
          return (
            <Modal show={true}>
              <div>
                <p>Do you really want to leave?</p>
                <button onClick={onCancel}>Cancel</button>
                <button onClick={onConfirm}>Ok</button>
              </div>
            </Modal>
          );
        }
        return <div>This is probably an anti-pattern but ya know...</div>;
      }}
    </NavigationPrompt>;
  5. Configure the NavigationPrompt API

    master

    The <NavigationPrompt/> component accepts the following props:

    PropTypeDescription
    whenbool or (Location, ?Location, ?HistoryAction) => boolDetermines if the prompt should be active. If a function is used, it receives the current location, the next location, and the action.
    children(data: {isActive: bool, onCancel: Function, onConfirm: Function}) => ReactElementA render function that receives the current state of the prompt.
    beforeConfirmFunctionA callback function that is called before the confirmation logic executes. Useful for performing cleanup tasks.
    beforeCancelFunctionA callback function called before the cancellation logic executes.
    afterConfirmFunctionA callback function called after the user confirms navigation.
    afterCancelFunctionA callback function called after the user cancels navigation.
    renderIfNotActiveboolIf true, children will be rendered even if props.when is falsy and isActive is false.
    allowGoBackboolIf true, uses the goBack method instead of push when navigating back. Note: This will always navigate back exactly 1 item, even if the user intended to go back further.
    disableNativebool(Not explicitly detailed in documentation, but available in props)
    matchMatchProvided by React Router.
    historyRouterHistoryProvided by React Router.
    locationLocationProvided by React Router.
  6. NavigationPrompt Props Reference

    master

    The NavigationPrompt component accepts the following props:

    PropTypeDescription
    whenbool or (location, nextLocation, action) => boolDetermines if the prompt should be triggered. If a function is provided, it receives the current location, the nextLocation, and the action (e.g., 'PUSH', 'POP').
    children(data: {isActive: bool, onCancel: Function, onConfirm: Function}) => ReactElementA render prop function that receives the prompt state and control functions.
    afterCancelFunctionCallback executed after the user cancels the navigation.
    afterConfirmFunctionCallback executed after the user confirms the navigation.
    beforeCancelFunctionA function that receives a callback cb. Call cb() to proceed with the cancellation. Useful for async logic.
    beforeConfirmFunctionA function that receives a callback cb. Call cb() to proceed with the confirmation. Useful for async logic.
    renderIfNotActiveboolIf true, the children will be rendered even when isActive is false. Defaults to false (renders null when inactive).
    disableNativeboolIf true, prevents the component from listening to the window beforeunload event (browser-level exit prompts).
    allowGoBackboolIf true, when a 'POP' action is intercepted, onConfirm will trigger history.goBack() instead of history.push('/').
    match, history, locationMatch, RouterHistory, LocationStandard React Router props provided via withRouter.
  7. Use the NavigationPrompt component

    master

    The NavigationPrompt component is a replacement for the standard React Router Prompt. It allows you to intercept navigation attempts and display custom UI (like a modal) instead of relying on the browser's default dialog.

    It uses a render prop pattern to provide the state and control functions needed to build your custom dialog.

    Key Props:

    • when: A boolean or a function (location, nextLocation, action) => boolean. If true (or the function returns true), navigation is blocked and the prompt is shown.
    • history: The history object from react-router-dom (automatically provided if using the default export).
    • location: The current location object (automatically provided if using the default export).
    • allowGoBack: Boolean. If true, when a user confirms a 'POP' action, the component will call history.goBack() instead of history.push().
    • disableNative: Boolean. If true, it prevents the component from attaching a beforeunload listener to the window (useful if you only want to block internal React Router navigation).
    • beforeConfirm: A function (callback) => void called when the user clicks 'confirm'. Use this to perform async tasks (like saving data) before proceeding.
    • beforeCancel: A function (callback) => void called when the user clicks 'cancel'.
    • afterConfirm: A callback function executed after navigation is confirmed.
    • afterCancel: A callback function executed after navigation is cancelled.
    • renderIfNotActive: A boolean. If true, the children function will still be called even when isActive is false.
    <NavigationPrompt when={this.props.isDirty}>
      {({isActive, onConfirm, onCancel}) => (
        <Modal show={isActive}>
          <div>
            <p>Do you really want to leave?</p>
            <button onClick={onCancel}>Cancel</button>
            <button onClick={onConfirm}>Ok</button>
          </div>
        </Modal>
      )}
    </NavigationPrompt>