# react-router-cache-route

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

Latest version **1.13.0** (published 2024-05-10) · ISC license · 0 weekly downloads

## Install

```sh
npm install react-router-cache-route
pnpm add react-router-cache-route
yarn add react-router-cache-route
bun add react-router-cache-route
```

## Health

**Score 15/100 (F)** — status: abandoned.

Positive: no vulnerabilities.

Warnings: low downloads; no types; no esm support.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 1.13.0 |
| Published | 2024-05-10 |
| First published | 2018-06-26 |
| Weekly downloads | 0 |
| License | ISC |
| TypeScript types | none |
| Module format | CommonJS |
| Dependencies | 2 |
| Unpacked size | 186.5 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 1175 |
| Author | CJY0208 |
| Maintainers | cjy0208 |
| Keywords | cache, cache route, react, react router, keep alive, keep alive route |

## Links

- npm: https://www.npmjs.com/package/react-router-cache-route
- Repository: https://github.com/CJY0208/react-router-cache-route
- npm.io page: https://npm.io/package/react-router-cache-route

## Dependencies (2)

- [react-freeze](https://npm.io/package/react-freeze.md) ^1.0.0
- [mini-create-react-context](https://npm.io/package/mini-create-react-context.md) ^0.4.1

## Alternatives

- [mobx-react](https://npm.io/package/mobx-react.md) — 2.8M weekly downloads
- [rc-tree](https://npm.io/package/rc-tree.md) — 2.6M weekly downloads
- [@react-oauth/google](https://npm.io/package/@react-oauth/google.md) — 1.3M weekly downloads
- [@wagmi/connectors](https://npm.io/package/@wagmi/connectors.md) — 877.0K weekly downloads
- [vee-validate](https://npm.io/package/vee-validate.md) — 836.4K weekly downloads

## Recent versions

- 1.13.0 (latest) — 2024-05-10
- 1.12.11 — 2022-05-30
- 1.12.10 — 2022-05-30
- 1.12.9 — 2022-05-16
- 1.12.8 — 2022-05-10
- 1.12.7 — 2022-04-06
- 1.12.6 — 2022-03-31
- 1.12.5 — 2022-02-09
- 1.12.4 — 2022-02-09
- 1.12.3 — 2022-02-09
- 1.12.2 — 2022-02-09
- 1.12.1 — 2021-11-18
- 1.12.0 — 2021-11-18
- 1.11.1 — 2021-06-11
- 1.11.0 — 2021-01-05
- … 37 more at https://npm.io/package/react-router-cache-route/versions

## README

# CacheRoute

[![size](https://img.shields.io/bundlephobia/minzip/react-router-cache-route.svg)](https://github.com/CJY0208/react-router-cache-route)
[![dm](https://img.shields.io/npm/dm/react-router-cache-route.svg)](https://github.com/CJY0208/react-router-cache-route)
![](https://komarev.com/ghpvc/?username=cjy0208-react-router-cache-route&label=VIEWS)

English | [中文说明](./README_CN.md)

Route with cache for `react-router` like `keep-alive` in Vue.

[Online Demo](https://codesandbox.io/s/cache-route-demo-2spfh)

**If you want `<KeepAlive />` only, try [react-activation](https://github.com/CJY0208/react-activation)**

**React v15+**

**React-Router v4+**

---

<img src="./docs/CacheRoute.gif">

---

## 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/ReactTraining/react-router/blob/master/packages/react-router/modules/Route.js#L41-L63

---

## Install

```bash
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)

```javascript
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                                                                                                                                                 |
| 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` 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](https://github.com/CJY0208/react-router-cache-route/issues/55) |

---

## Lifecycles

### Hooks

use `useDidCache` and `useDidRecover` to inject customer Lifecycle `didCache` and `didRecover`

```javascript
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`

```javascript
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.

```javascript
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.

```js
import { clearCache } from 'react-router-cache-route'

clearCache()
```

---
_Source: https://npm.io/package/react-router-cache-route · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
