react-router-hibernate
    TypeScript icon, indicating that this package has built-in type declarations

    0.3.0 • Public • Published

    React-Router-Hibernate

    A React Router <Switch> which can leave inactive routes mounted-but-inactive until you navigate back.

    Part of React Hibernate

    npm version test coverage dependencies status gzip size

    Overview

    By defaut, navigating from one <Route> to another in react-router will unmount the old route's tree. If you return to it, it will be remounted from scratch.

    This library adds <HibernatingSwitch> and <HibernatingRoute>: drop-in replacements for <Switch> and <Route> which do not immediately unmount components when you navigate away. If you return, the prior tree will be restored, local state and all.

    Example

    import { HibernatingSwitch, HibernatingRoute } from 'react-router-hibernate';
    
    // then render:
    <HibernatingSwitch maxCacheTime={60000}>
    
      {/* Use the "Hibernating" variants exactly like the standard ones */}
      <HibernatingRoute path="/foo" component={...} />
      <HibernatingRoute path="/bar" render={...} />
    
      {/* You can mix and match: use them alongside the normal react-router components */}
      <Route path="/baz" component={...} />
      <Redirect from="/something-else" to="/foo" />
    
      {/* If you have your own custom components, add an isHibernatingRoute prop */}
      <MyPrivateRoute path="/secret" component={...} isHibernatingRoute />
    
    </HibernatingSwitch>

    Props for HibernatingSwitch

    maxCacheSize (number, default: 5)

    Number of subtrees to keep in the cache, including the current one. path is used for the cache keys. Set a falsy value to disable.

    maxCacheTime (milliseconds, default: 5 minutes)

    Time after which a subtree is removed from the cache. Set a falsy value to disable.

    WrapperComponent (React component, default: none)

    A component which wraps all potentially-hibernatable routes. It receives a shouldUpdate prop. React-Pauseable-Containers was created for this.

    How it Works

    Each route's subtree is rendered via a React-Reverse-Portal, and the portal nodes are stored and rotated via a Limited-Cache.

    When you revisit a route which is still in the cache, its prior subtree is reattached. Because the elements and instances were not destroyed, all prior state is still present -- both React state and dom state.

    Preventing Extra Work in Inactive Routes

    Previously-rendered trees are still mounted when inactive: they're just not attached to the dom.

    HibernatingRoute will suppress the normal render cycle for inactive subtrees, but if a component in the subtree experiences a state change or context update then it will rerun. This is fundamental to React and cannot be avoided.

    For example: react-redux's useSelector hook works by forcing a rerender outside of the normal render cycle by changing local state -- so suppressing the normal render cycle is not enough.

    In most cases this is fine -- inactive subtrees still use minimal resources -- but if the component render is slow or has side effects then you may want to avoid running it at all.

    You can do that by setting a WrapperComponent which halts context updates. React-Pauseable-Containers was created for this: you can use its components directly, compose them together to make your WrapperComponent, or follow the examples to make your own from scratch.

    Roadmap

    • [x] Proof of concept
    • [x] Project scaffolding
    • [x] Core functionality
    • [x] Tests
    • [x] Demos
    • [x] Monorepo
    • [x] Initial release
    • [ ] Add useHibernatingEffect hook (successfully prototyped)
    • [ ] Add maxCacheTime override per-route (successfully prototyped)
    • [ ] Explore: Options to better control which/when to add a subtree
    • [ ] Explore: React-Router v6

    Known Issues

    "Cannot update a component from inside the function body of a different component" warning in React 16.13+

    • This will be addressed as part of supporting React-Router v6, when subtree activation will need to be done via a component instead of a callback.

    Install

    npm i react-router-hibernate

    DownloadsWeekly Downloads

    18

    Version

    0.3.0

    License

    MIT

    Unpacked Size

    44.7 kB

    Total Files

    25

    Last publish

    Collaborators

    • spautz