Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[v6] <Route path="app/*"> is matching apples/* #7529

Closed
thedanwoods opened this issue Jul 29, 2020 · 13 comments
Closed

[v6] <Route path="app/*"> is matching apples/* #7529

thedanwoods opened this issue Jul 29, 2020 · 13 comments
Assignees

Comments

@thedanwoods
Copy link

Version

6.0.0-beta.0

Test Case

https://codesandbox.io/s/heuristic-wiles-ycz48?file=/src/App.js

Steps to reproduce

In the sandbox above, click on the Cheeseburger link.

Expected Behavior

It should match the /cheeseburger/* path and render the <Cheeseburger /> component.

Actual Behavior

It gets caught by <Route path="/cheese/*"> and renders the <Cheese /> component.

Additionally, the <Link> in the <Cheese> component thinks we are in /cheese rather than /cheeseburger: the relative <Link to="details"> takes us to /cheese/details even though the current route is /cheeseburger.

This only happens the <Route>s are declared in this order, with the shorter word first:
<Route path="cheese/*" element={<Cheese />} />
<Route path="cheeseburger/*" element={<Cheeseburger />} />

It only happens when there is a trailing /*, e.g. <Route path="cheeseburger/*"> - I think you now always need a /* if there are sub-routes in the child component. It doesn't seem to happen if there is no /*, e.g. <Route path="cheeseburger">.

@timdorr
Copy link
Member

timdorr commented Jul 30, 2020

Related to #7423

@huttonr
Copy link

huttonr commented Sep 25, 2020

It appears that the compilePath function is at fault:

https://github.com/ReactTraining/react-router/blob/262b45dd8d6cbdc3a984259c5591ffc3de80d600/packages/react-router/index.tsx#L999

<Route path="/app/*" ... /> is compiling down to the RegExp match pattern: ^(/app)\/?(.*)$

This is causing matchPath('/app/*', '/apples') to match.

Incidentally, this also means that matchPath('/app', '/app?editing=true') doesn't match which makes little sense as search params shouldn't affect whether a route is matched.

This seems (possibly??) only to apply to Routes at the "root" level and not descendant or nested routes.

A more useful RegExp pattern for compilePath to resolve to in the case of /app/* would be ^(\/app)(\/.*|\?.*)?$

I'm not familiar enough with the inner workings of compilePath to submit a PR but perhaps this help to isolate the problem.

I, for one, am eagerly waiting for this to be fixed.

@stale
Copy link

stale bot commented Nov 24, 2020

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.
You can add the fresh label to prevent me from taking any action.

@stale stale bot added the stale label Nov 24, 2020
@caseyjhol
Copy link

This needs a fresh label.

@stale stale bot removed the stale label Nov 25, 2020
@gabceb
Copy link

gabceb commented Dec 23, 2020

Hi React Router team. We are using the new awesome v6-beta on quite large apps and we have started seeing this issue as well. Any updates would be appreciated

@timdorr timdorr added the fresh label Dec 23, 2020
@jjenzz
Copy link

jjenzz commented Jan 10, 2021

I'm having a similar issue with NavLink. Links are active for incorrect pages. For example, /foo/1 would be active on /foo/12, /foo/13 etc.

@damikun

This comment has been minimized.

@stefensuhat
Copy link

is this merged?

@jsmouret
Copy link

jsmouret commented Jun 10, 2021

Current workaround is to use patch-package

Add this to your package.json

  "scripts": {
    "postinstall": "patch-package"
  },
  "devDependencies": {
    "patch-package": "^6.4.7"
  }

and copy this to into patches/react-router+6.0.0-beta.0.patch

diff --git a/node_modules/react-router/index.js b/node_modules/react-router/index.js
index 2b95c08..8ed2b8d 100644
--- a/node_modules/react-router/index.js
+++ b/node_modules/react-router/index.js
@@ -16,8 +16,8 @@ function F(a){var b=[];Children.forEach(a,function(a){if(isValidElement(a))if(a.
 function M(a,b,c){void 0===c&&(c="");"string"===typeof b&&(b=parsePath(b));b=b.pathname||"/";if(c)if(c=c.replace(/^\/*/,"/").replace(/\/+$/,""),b.startsWith(c))b=b===c?"/":b.slice(c.length);else return null;a=O(a);P(a);var d=null;for(c=0;null==d&&c<a.length;++c)a:{d=b;for(var e=a[c][1],g="/",h={},I=[],n=0;n<e.length;++n){var t=e[n],u="/"===g?d:d.slice(g.length)||"/";u=Q({path:t.path,caseSensitive:t.caseSensitive,end:n===e.length-1},u);if(!u){d=null;break a}g=L([g,u.pathname]);h=f({},h,{},u.params);
 I.push({route:t,pathname:g,params:k(h)})}d=I}return d}function O(a,b,c,d,e){void 0===b&&(b=[]);void 0===c&&(c="");void 0===d&&(d=[]);void 0===e&&(e=[]);a.forEach(function(a,h){var g=L([c,a.path]),n=d.concat(a);h=e.concat(h);a.children&&O(a.children,b,g,n,h);b.push([g,n,h])});return b}function P(a){var b=a.reduce(function(a,b){b=b[0];a[b]=R(b);return a},{});S(a,function(a,d){var c=a[2];a=b[a[0]];var g=d[2];d=b[d[0]];return a!==d?d-a:T(c,g)})}var U=/^:\w+$/,V=2,W=1,X=10,Y=-2;
 function Z(a){return"*"===a}function R(a){a=a.split("/");var b=a.length;a.some(Z)&&(b+=Y);return a.filter(function(a){return!Z(a)}).reduce(function(a,b){return a+(U.test(b)?V:""===b?W:X)},b)}function T(a,b){return a.length===b.length&&a.slice(0,-1).every(function(a,d){return a===b[d]})?a[a.length-1]-b[b.length-1]:0}function S(a,b){var c=a.slice(0);a.sort(function(a,e){return b(a,e)||c.indexOf(a)-c.indexOf(e)})}
-function Q(a,b){"string"===typeof a&&(a={path:a});var c=a;a=c.path;var d=c.caseSensitive;c=c.end;c=aa(a,void 0===d?!1:d,void 0===c?!0:c);d=c[1];c=b.match(c[0]);if(!c)return null;b=c[1];var e=c.slice(2);d=d.reduce(function(a,b,c){c=e[c];try{var d=decodeURIComponent(c.replace(/\+/g," "))}catch(t){"production"!==process.env.NODE_ENV?m(!1,'The value for the URL param "'+b+'" will not be decoded because the string "'+(c+'" is a malformed URL segment. This is probably due to a bad percent encoding (')+
-(t+").")):void 0,d=c}a[b]=d;return a},{});return{path:a,pathname:b,params:d}}function aa(a,b,c){var d=[],e="^("+a.replace(/^\/*/,"/").replace(/\/?\*?$/,"").replace(/[\\.*+^$?{}|()[\]]/g,"\\$&").replace(/:(\w+)/g,function(a,b){d.push(b);return"([^\\/]+)"})+")";a.endsWith("*")?(a.endsWith("/*")&&(e+="\\/?"),d.push("*"),e+="(.*)"):c&&(e+="\\/?");c&&(e+="$");return[new RegExp(e,b?void 0:"i"),d]}
+function Q(a,b){"string"===typeof a&&(a={path:a});var c=a;a=c.path;var d=c.caseSensitive;c=c.end;c=aa(a,void 0===d?!1:d,void 0===c?!0:c);d=c[1];c=(b.endsWith('/')?b:b+'/').match(c[0]);if(!c)return null;b=c[1];var e=c.slice(2);d=d.reduce(function(a,b,c){c=e[c];try{var d=decodeURIComponent(c.replace(/\+/g," "))}catch(t){"production"!==process.env.NODE_ENV?m(!1,'The value for the URL param "'+b+'" will not be decoded because the string "'+(c+'" is a malformed URL segment. This is probably due to a bad percent encoding (')+
+(t+").")):void 0,d=c}a[b]=d;return a},{});return{path:a,pathname:b,params:d}}function aa(a,b,c){var d=[],e="^("+a.replace(/^\/*/,"/").replace(/\/?\*?$/,"").replace(/[\\.*+^$?{}|()[\]]/g,"\\$&").replace(/:(\w+)/g,function(a,b){d.push(b);return"([^\\/]+)"})+")";a.endsWith("*")?(a.endsWith("/*")&&(e+="\\/+"),d.push("*"),e+="(.*)"):c&&(e+="\\/?");c&&(e+="$");return[new RegExp(e,b?void 0:"i"),d]}
 function J(a,b){void 0===b&&(b="/");var c="string"===typeof a?parsePath(a):a;a=c.pathname;var d=c.search;d=void 0===d?"":d;c=c.hash;c=void 0===c?"":c;return{pathname:a?ba(a,a.startsWith("/")?"/":b):b,search:d,hash:c}}function L(a){return a.join("/").replace(/\/\/+/g,"/")}function ba(a,b){var c=b.replace(/\/+$/,"").replace(/\/\/+/g,"/").split("/");a.replace(/\/\/+/g,"/").split("/").forEach(function(a){".."===a?1<c.length&&c.pop():"."!==a&&c.push(a)});return 1<c.length?L(c):"/"}
 function generatePath(a,b){void 0===b&&(b={});return a.replace(/:(\w+)/g,function(a,d){null==b[d]?"production"!==process.env.NODE_ENV?l(!1,'Missing ":'+d+'" param'):l(!1):void 0;return b[d]}).replace(/\/*\*$/,function(){return null==b["*"]?"":b["*"].replace(/^\/*/,"/")})};
 function useBlocker(a,b){void 0===b&&(b=!0);z()?void 0:"production"!==process.env.NODE_ENV?l(!1,"useBlocker() may be used only in the context of a <Router> component."):l(!1);var c=useContext(r).navigator;useEffect(function(){if(b){var d=c.block(function(b){var c=f({},b,{retry:function(){d();b.retry()}});a(c)});return d}},[c,a,b])};

@chaance
Copy link
Collaborator

chaance commented Jul 28, 2021

Working on it

@chaance chaance self-assigned this Jul 28, 2021
@joacub

This comment has been minimized.

@chaance
Copy link
Collaborator

chaance commented Aug 11, 2021

Fixed in #7874, release coming this week!

@chaance chaance closed this as completed Aug 11, 2021
@joacub
Copy link

joacub commented Aug 11, 2021

Fixed in #7874, release coming this week!

nice!!!!!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests