Skip to content

Latest commit

 

History

15 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🚀 use-back-stack

A React hook that turns browser history into a native-like back stack, so modals, drawers and other overlays close with the back button instead of leaving the page.

npm version

📱 Demo Comparison

Before After
Before After
Modals remain open when going back Modals can be closed with back button

✨ Key Features

  • 🔙 Close modals, drawers, and other UI elements with the browser's back button
  • 📚 When multiple overlays are open, they are closed in reverse order (last opened first)
  • 🧹 Closing an overlay by any means (button, backdrop, Escape) pops the history entry it pushed
  • 🔗 Keeps the current URL, including the hash, and preserves the history.state your router owns
  • 📱 Provides a mobile app experience on the web similar to PWAs
  • ⚛️ Works with any React framework, and is safe to render on the server

📦 Installation

npm install use-back-stack

🔍 Usage

import { useState } from "react";
import { useBackStack } from "use-back-stack";

function App() {
   // Drawer state management
   const [isDrawer1Open, setIsDrawer1Open] = useState(false);
   const [isDrawer2Open, setIsDrawer2Open] = useState(false);

   // Using the hook
   useBackStack([
      { isOpen: isDrawer1Open, setIsOpen: setIsDrawer1Open },
      { isOpen: isDrawer2Open, setIsOpen: setIsDrawer2Open },
   ]);

   return (
      <div>
         <button onClick={() => setIsDrawer1Open(true)}>Open Drawer 1</button>
         <button onClick={() => setIsDrawer2Open(true)}>Open Drawer 2</button>

         {isDrawer1Open && (
            <div className="drawer">
               <h2>Drawer 1</h2>
               <button onClick={() => setIsDrawer1Open(false)}>Close</button>
            </div>
         )}

         {isDrawer2Open && (
            <div className="drawer">
               <h2>Drawer 2</h2>
               <button onClick={() => setIsDrawer2Open(false)}>Close</button>
            </div>
         )}
      </div>
   );
}

📖 API

const close = useBackStack(overlays: { isOpen: boolean; setIsOpen: (isOpen: boolean) => void }[]);

The hook keeps exactly one history entry per open overlay. Opening an overlay pushes an entry, and closing one removes it — no matter whether it was closed by the back button or by your own setIsOpen(false).

The returned close() closes the topmost open overlay, which is handy for a shared close button or backdrop:

const close = useBackStack([{ isOpen, setIsOpen }]);

<div className="backdrop" onClick={close} />;

🔄 Migrating from use-back-stack-overlay

This package used to be published as use-back-stack-overlay. Only the names changed — the arguments and the return value are the same:

-import { useBackStackOverlay } from "use-back-stack-overlay";
+import { useBackStack } from "use-back-stack";

-useBackStackOverlay([{ isOpen, setIsOpen }]);
+useBackStack([{ isOpen, setIsOpen }]);

⚠️ Notes

  • If your app navigates (for example router.push) while an overlay is open, the entry on top of the stack no longer belongs to the hook. Closing the overlay then leaves the history untouched instead of navigating your user away.
  • Overlays that are still open when the component unmounts keep their history entries; the next back press consumes them without a visible change.

About

A React hook that turns browser history into a native-like back stack, so modals, drawers and other overlays close with the back button

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages