License
- ISC
- Yesattribution
- Permissivelinking
- Permissivedistribution
- Permissivemodification
- Nopatent grant
- Yesprivate use
- Permissivesublicensing
- Notrademark grant
Downloads
Readme
⚠️⚠️⚠️ React Router v6+ is NOT supported ⚠️⚠️⚠️
CacheRoute
English | 中文说明
Route with cache for react-router
like keep-alive
in Vue.
Online Demo
If you want <KeepAlive />
only, try react-activation
React v15+
React-Router v4/v5
Problem Scenarios
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/remix-run/react-router/blob/v5.3.4/packages/react-router/modules/Route.js#L46-L61
Install
npm install react-router-cache-route --save
# or
yarn add react-router-cache-route
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 whenString
/ 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
cacheKey
String
/ Function
-
For imperative control caching
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.
unmount (UNSTABLE)
Boolean
false
Whether to unmount the real dom node after cached, to save performance (Will cause losing the scroll position after recovered, fixed with saveScrollPosition
props)
saveScrollPosition (UNSTABLE)
Boolean
false
Save scroll position
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
orREPLACE
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 whichFunction
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 (
// ...
)
}
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 (
// ...
)
}
}
Drop cache
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')
...
Clear cache
You can clear cache with clearCache
function.
import { clearCache } from 'react-router-cache-route'
clearCache()