Route with cache for react-router
like keep-alive
in Vue.
React v16+
React-Router v4+
Using Route
, component can not be cached while going forward or back which lead to losing data and interaction
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.
npm install react-router-cache-route --save
Can use CacheRoute
with component
, render
, children
prop
DO NOT put it in Switch
component, use CacheSwitch
instead
Use when
prop to decide when you need to use the cache, the optional value is [forward
, back
, always
] , forward
default
Use className
prop for adding custom style to the cache wrapper component
You can also customize how the cached components are hidden using behavior
props which would return a props
effective on the wrapper component
import React from 'react'
import { HashRouter as Router, Switch, Route } from 'react-router-dom'
import CacheRoute, { CacheSwitch } from 'react-router-cache-route'
import List from './components/List'
import Item from './components/Item'
import List2 from './components/List2'
import Item2 from './components/Item2'
const App = () => (
<Router>
{/*
Can also use render, children props
<CacheRoute exact path="/list" render={props => <List {...props} />} />
or
<CacheRoute exact path="/list">
{props => <List {...props} />}
</CacheRoute>
or
<CacheRoute exact path="/list">
<div>
Support muiltple children
</div>
<List />
</CacheRoute>
*/}
<CacheRoute exact path="/list" component={List} when="always" />
<Switch>
<Route exact path="/item/:id" component={Item} />
</Switch>
<CacheSwitch>
<CacheRoute
exact
path="/list2"
component={List2}
className="custom-style"
behavior={cached => (cached ? {
style: {
position: 'absolute',
zIndex: -9999,
opacity: 0,
visibility: 'hidden',
pointerEvents: 'none'
},
className: '__CacheRoute__cached'
} : {
className: '__CacheRoute__uncached'
})}
/>
<Route exact path="/item2/:id" component={Item2} />
<Route
render={() => (
<div>404 Not Found</div>
)}
/>
</CacheSwitch>
</Router>
)
export default App
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, ...args) {
super(props, ...args)
props.cacheLifecycles.didCache(this.componentDidCache)
props.cacheLifecycles.didRecover(this.componentDidRecover)
}
componentDidCache = () => {
console.log('List cached')
}
componentDidRecover = () => {
console.log('List recovered')
}
render() {
return (
// ...
)
}
}
You can manually control the cache with cacheKey
prop and dropByCacheKey
function.
import CacheRoute, { dropByCacheKey, getCachingKeys } from 'react-router-cache-route'
...
<CacheRoute ... cacheKey="MyComponent" />
...
console.log(getCachingKeys()) // will receive ['MyComponent'] if CacheRoute is cached which `cacheKey` prop is 'MyComponent'
...
dropByCacheKey('MyComponent')
...