CJY0208 / react-router-cache-route

Route with cache for react-router V5 like <keep-alive /> in Vue
https://www.npmjs.com/package/react-router-cache-route
MIT License
1.14k stars 110 forks source link

props.match not available while cached #147

Open EwanRoycroft opened 2 years ago

EwanRoycroft commented 2 years ago

Description

I have an application where my route reacts to changes to the props.match object passed as part of the route props. When my route is cached, props.match become unavailable and the route re-renders in the background. When the route is restored, it must re-render, which has some unwanted side-effects for my application.

Steps to reproduce

Using the following application:

import React from 'react';
import { HashRouter as Router, Link } from 'react-router-dom';
import {
    CacheSwitch,
    CacheRoute,
    useDidCache,
    useDidRecover,
} from 'react-router-cache-route';

const Route = function (props) {
    console.log(`Route ${props.number} rendered:`, props.match);

    useDidCache(() => console.log(`Route ${props.number} cached`));
    useDidRecover(() => console.log(`Route ${props.number} recovered`));

    return props.children;
};

const App = function () {
    return (
        <Router>
            <CacheSwitch>
                <CacheRoute
                    exact
                    path="/route1"
                    render={(renderProps) => (
                        <Route {...renderProps} number="1">
                            <h1>Route 1</h1>
                            <Link to="/route2">Go to route 2</Link>
                        </Route>
                    )}
                />
                <CacheRoute
                    exact
                    path="/route2"
                    render={(renderProps) => (
                        <Route {...renderProps} number="2">
                            <h1>Route 2</h1>
                            <Link to="/route1">Go to route 1</Link>
                        </Route>
                    )}
                />
            </CacheSwitch>
        </Router>
    );
};

export default App;
  1. Navigate to /route1.
  2. Click "Go to route 2", observe the console.

You will see that route 1 first renders, props.match is available to it:

Route 1 rendered: {path: '/route1', url: '/route1', isExact: true, params: {…}}

However, when route 2 is loaded, route 1 re-renders with props.match unavailable:

Route 1 rendered: {__isComputedUnmatch: true}
Route 2 rendered: {path: '/route2', url: '/route2', isExact: true, params: {…}}
Route 1 cached
Route 1 rendered: {__isComputedUnmatch: true}
  1. Now click on "Go to route 1", observe the console.

You will see that route 1 recovers and props.match is available once again:

Route 1 rendered: {path: '/route1', url: '/route1', isExact: true, params: {…}}
Route 2 rendered: {__isComputedUnmatch: true}
Route 1 recovered
Route 2 cached
Route 1 rendered: {path: '/route1', url: '/route1', isExact: true, params: {…}}
Route 2 rendered: {__isComputedUnmatch: true}
CJY0208 commented 2 years ago

looks like you need to rely on props.match to do something?

which version of cache-route you are using? Can the previous version work?

If the old version takes effect, it may be a recent change that has caused the problem, you can try to use the latest version 1.12.8 to see if the problem is fixed

If not, you may need to deal with props.match yourself.

such as:

function Wrapper(props) {
  const matchRef = useRef(props.match)
  matchRef.current = 'path' in props?.match ? props.match : matchRef.current

 return (
   <YourComponent {...props} match={matchRef.current} />
 )
}