@mixtiles/cache-router

cache-router for react-router base on react v15+ and router v4+

Usage no npm install needed!

<script type="module">
  import mixtilesCacheRouter from 'https://cdn.skypack.dev/@mixtiles/cache-router';
</script>

README

Mixtiles Cache Router

A Router with built in cache for react-router

React v15+

React-Router v4+



Problem

Using Route, component can not be cached while going forward or back which lead to losing data and interaction


Reason & Solution

Component would be unmounted when Route was unmatched

After reading source code of Route we found that using children prop as a function could help to control rendering behavior.

Hiding instead of Removing would fix this issue.

https://github.com/ReactTraining/react-router/blob/master/packages/react-router/modules/Route.js#L41-L63


Install

npm install @mixtiles/cache-router --save
# or
yarn add @mixtiles/cache-router

Usage

Replace Route with CacheRoute

Replace Switch with CacheSwitch (Because Switch only keeps the first matching state route and unmount the others)

import React from 'react'
import { HashRouter as Router, Route } from 'react-router-dom'
import CacheRoute, { CacheSwitch } from 'react-router-cache-route'

import List from './views/List'
import Item from './views/Item'

const App = () => (
  <Router>
    <CacheSwitch>
      <CacheRoute exact path="/list" component={List} />
      <Route exact path="/item/:id" component={Item} />
      <Route render={() => <div>404 Not Found</div>} />
    </CacheSwitch>
  </Router>
)

export default App

CacheRoute props

name type default description
when String / Function "forward" Decide when to cache
className String - className prop for the wrapper component
behavior Function cached => cached ? { style: { display: "none" }} : undefined Return props effective on the wrapper component to control rendering behavior
multiple (React v16.2+) Boolean / Number false Allows different caches to be distinguished by dynamic routing parameters. When the value is a number, it indicates the maximum number of caches. When the maximum value is exceeded, the oldest updated cache will be cleared.

CacheRoute is only a wrapper component that works based on the children property of Route, and does not affect the functionality of Route itself.

For the rest of the properties, please refer to https://reacttraining.com/react-router/


About when

The following values can be taken when the type is String

  • [forward] Cache when forward behavior occurs, corresponding to the PUSH or REPLACE action in react-router
  • [back] Cache when back behavior occurs, corresponding to the POP action in react-router
  • [always] Always cache routes when leave, no matter forward or backward

When the type is Function, the component's props will be accepted as the first argument, return true/false to determine whether to cache.


CacheSwitch props

name type default description
which Function element => element.type === CacheRoute <CacheSwitch> only saves the first layer of nodes which type is CacheRoute by default, which prop is a function that would receive a instance of React Component, return true/false to decide if <CacheSwitch> need to save it, reference #55

Lifecycles

Hooks

use useDidCache and useDidRecover to inject customer Lifecycle didCache and didRecover

import { useDidCache, useDidRecover } from 'react-router-cache-route'

export default function List() {

  useDidCache(() => {
    console.log('List cached 1')
  })

  // support multiple effect
  useDidCache(() => {
    console.log('List cached 2')
  })

  useDidRecover(() => {
    console.log('List recovered')
  })

  return (
    // ...
  )
}

2 more hooks that are available are useIsInActivePage and useIsInCachedRecoveredPage

useIsInActivePage - returns wether or not the page is the active page the user is observing

useIsInCachedRecoveredPage- returns wether or not the page is in a recovered state

Class Component

Component with CacheRoute will accept one prop named cacheLifecycles which contains two functions to inject customer Lifecycle didCache and didRecover

import React, { Component } from 'react'

export default class List extends Component {
  constructor(props) {
    super(props)

    props.cacheLifecycles.didCache(this.componentDidCache)
    props.cacheLifecycles.didRecover(this.componentDidRecover)
  }

  componentDidCache = () => {
    console.log('List cached')
  }

  componentDidRecover = () => {
    console.log('List recovered')
  }

  render() {
    return (
      // ...
    )
  }
}

cachedNavigation

Cache Router exports a cached navigation function. This function is a wrapper around the history API object. The function allows the caller to indicate wether or he would like to navigate to a new instance of the route, or simply go to the last cached version of that route.

cachedNavigation can offer either a push or a replace method, similar to history.push/history.replace