4.0.0
https://reacttraining.com/react-router/web/example/recursive-paths
In the mini browser, put a trailing slash after a resource like: /3/
nested url should look like /3/2
nested url looks like /3//2
Is this something thats possible?
That is what the strict
prop is for. I'm not in a position to test it right now, but I believe that that would fix the recursive example. Anyways, once relative path support is merged in, this will be moot for most users since React Router will handle the path joining for them.
The strict
didn't help my case because I'd need to support both trailing and non trailing slash. This does have to do with relative paths. So for now, I'm removing the trailing slash from match.url
when combining it with my relative path. This is messy but will have to do until your PR is merged in. Any plans to fix the merge conflicts and merge it in?
Relative <Route>
s and <Link>
s should happen at the same time (probably a short beta to verify they work as expected). I have the code rebased, but I am waiting on a decision for what to do when the parent match is null
(caused by using <Route children>
) before moving forward.
For the time being I would just use
const join = (base, path) => {
return base.charAt(base.length-1) === '/'
? base.slice(0, -1) + path
: base + '/' + path
}
<Route path={join(match.url, '/rest')} component={Rest} />
Very unexpected behavior at a first glance. Some guidance would be nice :)
We use a lot of this <Link to={`${match.url}/foo`}>Foo</Link>
which will result in example.com/bar/foo
or example.com/bar//foo
whether you use example.com/bar
or example.com/bar/
from a user point of view.
Note: a node path's like join function is totally fine for me :)
Experiencing the same unpredictable route match.url trailing slashes, especially with nested routes
I solved this at the parent route level by redirecting to the no-slash-url.
<Switch>
...
<Redirect strict from={url + '/'} to={url} />
<Route path={url} component={App} />
</Switch>
This way the url matched never contains the trailing slash. Just another option.
Yeah I'd like some guidance. Should I be aiming to have slashes at end or not? Coming from WordPress the answer is yes I'd like a / at the end of everything. As I began to re-work my code to support that I begin to see example.com/bar//foo as well, making me think no trailing slash is the standard with React.
I struggled for quite some time to get a workaround for this.
I also learned about strict
, but as @shawnmclean mentioned, it doesn't fix the main issue here: to configure React Router (RR) to remove the trailing slash at the end of the URL by default.
This comment on a strict-related issue worked for me:
https://github.com/ReactTraining/react-router/issues/4170#issuecomment-269795053
Our structure ended up like this:
const RemoveTrailingSlash = ({location}) => {
...
}
...
<Router>
<Navigation {...props} />
<Route path="/" render={RemoveTrailingSlash} />
<Grid>
<Switch>
<Route...
I really suggest there is a configuration on RR that would remove all the trailing slashes on URLs.
Hope this comment can help people looking for this.
@leite08 thanks for the solution, it works for most cases. But when I have top-level <Route>
component with multilingual configuration, e.g path="/:lang(en|it)?"
and try to use <Link to={`${match.url}/foo`}
so URL could respect the current matched language, it works only if lang param is not omitted e.g: site.com/en/foo
, but for default case, I end up with a URLs like this: site.com//foo
. It happens because match.url
contains slash for root level URL.
Having two routes -- the first being strict
and exact
and the other being a fallback route -- solves the problem.
<Redirect strict exact from={match.path} to={`${match.url}/foo`} />
<Redirect exact from={match.path} to={`${match.url}foo`} />
Any thoughts on potential problems/caveats?
I think trailing slash should be removed from match.url. This behavior is not obvious and should be clarified in documentation
It is also "Not The Unix Way" of doing things to use /something when it's not at root.
Having two routes -- the first being
strict
andexact
and the other being a fallback route -- solves the problem.<Redirect strict exact from={match.path} to={`${match.url}/foo`} /> <Redirect exact from={match.path} to={`${match.url}foo`} />
Any thoughts on potential problems/caveats?
This is good I will use this double spec approach if my troubles come again.
I'm facing the same problem,
I solved it in the main App's Switch Component using regex to delete the last trailing slash from the path
const pathname = window.location.pathname
// ...
<Switch>
{
pathname!== "/" && (/\/$/).test(pathname) &&
<Redirect to={pathname.slice(0, -1)} />
}
<PrivateRoute path={'/'} exact component={Dashboard}/>
<Route path={'/login'} exact component={Account}/>
...
</Switch>
It's working now but looks a little bit not right!
I was using @filoxo 's solution, but it recently stopped working in the 5.0.1 release
Any progress?
I was using @filoxo 's solution, but it recently stopped working in the 5.0.1 release
@dylanwulf You can try to use the following code, it works for me with the 5.0.1 release :
<Switch>
{/* Removes trailing slashes */}
<Route
path="/:url*(/+)"
exact
strict
render={({ location }) => (
<Redirect to={location.pathname.replace(/\/+$/, "")} />
)}
/>
{/* Removes duplicate slashes in the middle of the URL */}
<Route
path="/:url(.*//+.*)"
exact
strict
render={({ match }) => (
<Redirect to={`/${match.params.url.replace(/\/\/+/, "/")}`} />
)}
/>
A little bit hackish but I get correcting routing also with:
/foo/////bar
/foo/bar///
I used the following code in my main component I define the router, but I'm not sure If this is the best practice for React Router
if (props.location.pathname.endsWith('/')) {
props.location.pathname = props.location.pathname.slice(0, -1);
}
I did a workaround:
export const path = url => {
const fixedPath = url.endsWith('/')
? path(url.substring(0, url.length - 1))
: url;
return fixedPath;
};
then:
<Redirect to={path('/dashboard/')} />
// returns => /dashboard
<Redirect to={path('/dashboard///')} />
// returns => /dashboard
I tried the workarounds above that detect the trailing '/' and fix it with a <Redirect/>
but they triggered a page reload at every redirect.
To fix that I used this code instead:
const pathname = window.location.pathname;
if(pathname !== "/" && (/\/$/).test(pathname)){
props.history.replace(pathname.slice(0, -1));
}
Using replace removed the trailing space without reloading the page.
@divonelnc, did you check for other browsers?
@HosseinAlipour Tested on Chrome, Firefox, and Edge so far. Any reason why it wouldn't work on some browsers?
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.
This issue is not a stale stupid bot
I am not sure if this is related but I fixed the my trailing slash issues by changing my webpack
config.
If I started webpack-dev-server
within my /src
folder and if one of the folder names within my /src
folder clashed with a route name I got an additional trailing slash after a browser refresh.
I started webpack-dev-server
in another folder and it worked fine.
My problem is that if my nested routes are in a parent route like /supervisor
it works, if my parent route is ''
then it becomes '/'
with useRouteMatch
.
My workaround:
const { path, url } = useRouteMatch();
<Link to={`${url.endsWith('/') ? url.slice(0, -1) : url}/announcement`} />
<Route path={`${path.endsWith('/') ? path.slice(0, -1) : path}/announcement`} />
Adding a <Redirect>
is the cleanest solution I could find
function App() {
const { pathname } = useLocation();
return (
<div>
<Switch>
<Redirect from="/:url*(/+)" to={pathname.slice(0, -1)} />
<Route exact path="/" component={Home} />
<Route path="/test-page" component={TestPage} />
</Switch>
</div>
);
}
Credit to: https://jasonwatmore.com/post/2020/03/23/react-router-remove-trailing-slash-from-urls
It is not enough to build Link
s and Route
s in the nested routes.
useRouteMatch
continues to return a slash for path
and url
instead of an empty string, which does not allow to construct an url like that:
`${url}/announcement`
<Redirect from="/:url*(/+)" to={pathname.slice(0, -1)} />
Hey just want to let you know that navigating to something like /hello//world with this redirect pattern results in the url being rewritten in an unexpected manner (to /hello in this example). I would not recommend using this solution.
There is no need to navigate to a url ending in /
, if the url is ''
then it becomes automatically and in any case '/'
, which is annoying for composing sub-routes.
In my case it works perfectly if I have /prefix
, for example, but in my storybook without 'base' it doesn't work.
The only solution that works for me is: https://github.com/ReactTraining/react-router/issues/4841#issuecomment-617053320
@dylanwulf You can try to use the following code, it works for me with the 5.0.1 release :
<Switch> {/* Removes trailing slashes */} <Route path="/:url*(/+)" exact strict render={({ location }) => ( <Redirect to={location.pathname.replace(/\/+$/, "")} /> )} /> {/* Removes duplicate slashes in the middle of the URL */} <Route path="/:url(.*//+.*)" exact strict render={({ match }) => ( <Redirect to={`/${match.params.url.replace(/\/\/+/, "/")}`} /> )} />
A little bit hackish but I get correcting routing also with:
/foo/////bar
/foo/bar///
For those interested in leveraging redirects, here's a slight improvement on removing all extra slashes:
{/* Removes duplicate slashes */}
<Route exact strict path="(.*//+.*)" render={({ location }) => <Redirect to={location.pathname.replace(/\/\/+/g, '/')} />} />
This handles cases where you have extra slashes at the beginning, middle, or end and makes all replacements at once so you don't have to chain redirects (ie ///hello//world//url -> /hello//world//url -> /hello/world//url -> /hello/world/url).
+1 on @jrrdev approach to removing the trailing slash.
Most helpful comment
I think trailing slash should be removed from match.url. This behavior is not obvious and should be clarified in documentation