Comments (8)
Cool idea, I was wondering if I could do something like that in userspace. I agree it would be weird for RR to make assumptions about this, especially if it's easy for consumers to create the behavior they want.
from react-router.
Hmm... since your /b
loader said to replace('c')
, it's replacing the /a
entry since /b
was never actually added to the stack.
[/]
[/, /a] push /a
[/, /b/c] replace /a with /b/c
[/] back pops /b/c
from react-router.
Yeah, but that loader is firing as a result of a nav to /b
, right? So my expectation was that there should be a /b
entry to replace. Again, I could be wrong and this is how it's supposed to work, but I find it very strange if so.
I find it strange because I expected this technique to be precisely the way you do what I'm trying to do here, namely have navs to /b
go to /b/c
in an unobtrusive way, i.e., one that doesn't cause back button loops (which you get if you redirect without replacing) or weird loader timing issues (harder to explain but I can if necessary).
from react-router.
I think that's the difference between the new replace
API and redirect
(which works the way you expect).
Since RR doesn't really go through a server, it's manipulating history state directly. I think this is quite clear what's happening.
replace
This is a small wrapper around redirect that will trigger a client-side redirect to the new location usinghistory.replaceState
instead ofhistory.pushState
.
from react-router.
@kiliman's explanation above is accurate - loaders run before history is updated to avoid URL flickers through redirects. This is also how browsers handle document request redirects. So when you navigate to /b
you're still on /a
while loaders are running and therefore replace
will replace /a
while redirect
will push /b/c
onto the stack (instead of /b
).
namely have navs to /b go to /b/c in an unobtrusive way, i.e., one that doesn't cause back button loops (which you get if you redirect without replacing)
Can you explain the back button loop you're referring to? It seems your own example is confirming that redirect
does what you are looking for - why do you need to reach for replace
?
from react-router.
Think of it like <Link to="/b/c" replace>
- you replace /a
with /b/c
. but instead of having to decide to replace at the call site, you can decide to replace in the loader
from react-router.
I see. I think I was misremembering what redirect
does. I thought it added a history entry for the intermediate route ['/a', '/b', '/b/c']
, but it doesn't. This makes sense. Here is a version of my repro that changes it to redirect
and it works as expected.
https://stackblitz.com/edit/rr-6-26-replace-bug-e3uskm?file=src%2Fmain.tsx
Loop example with redirect
https://console-jgv0as6ki-oxidecomputer.vercel.app/projects/mock-project
Here is an example of a back button loop I have encountered with redirect
, which might be what gave me the wrong idea of how it worked. If you click this link and press back, you get a loop.
The route looks like this (source):
<Route path="projects/:project" element={null} loader={() => redirect('instances')} />
I assume this behavior is because on initial page load, there is no /a
to sit on while /b
is replaced with /b/c
. I wonder if it would be reasonable or possible for redirect
to behave like replace
in this situation.
replace()
version without loop
https://console-dw8pwzjd9-oxidecomputer.vercel.app/projects/mock-project
The version that uses replace
doesn't have this problem.
<Route path="projects/:project" element={null} loader={() => replace('instances')} />
<Navigate replace>
version without loop
To avoid this, my current production version of that line looks like this (source):
<Route path="projects/:project" element={<Navigate to="instances" replace />} />
https://console-kbcvkg2po-oxidecomputer.vercel.app/projects/mock-project
I also have written the code so we never actually link to the URL that needs to redirect anyway. We always link straight to the target (source):
project: (params: Project) => `${projectBase(params)}/instances`,
from react-router.
I wonder if it would be reasonable or possible for redirect to behave like replace in this situation.
Ah ok I see - so when you directly enter on a route and redirect
it's a push - and then if you click back it re-runs that loader and redirects again, pushing you right back to where you were. So you want replace
on initial load but redirect
on subsequent SPA navs?
I don't know if it's safe for RR to make the assumption that every redirect on initial loader execution should behave as a replace
- that feels like app-specific logic. You may be able to write a simple wrapper that does something like:
function appRedirect(path) {
return router.state.initialized ? replace(path) : redirect(path);
}
Or you could use a isFirstLoad
module-scoped variable or something similar
from react-router.
Related Issues (20)
- [Bug]: Unable to match a url that ends in an equal sign HOT 1
- [Bug]: optional segments with dynamic segments HOT 1
- [Bug]: State is not preserved in a component tree when switching to render via custom `<Routes location={location}>` prop
- [Bug]: undefined is not an object (evaluating ' request.signal.aborted ')
- [Bug]: "TypeError: URL constructor: // is not a valid URL" while using data router HOT 9
- [Bug]: Relative option is not work in useNavigate HOT 3
- [Bug]: (a11y)-Multiple accessibility issues with React-Router HOT 1
- [Bug]: The global state manager does not work in conjunction with react-router-dom HOT 1
- [Bug]: encoded # in path parameter causes route to be evaluated differently
- [Bug]: generatePath/matchPath don't handle encoding/decoding `/` the same HOT 1
- [Bug]: Support non-standard HTTP methods in Resource Routes HOT 3
- [Bug]: react-router seems to depend on vulnerable versions of path-to-regexp HOT 8
- [Bug]: react-router-dom v5 uses vulnerable version of path-to-regexp HOT 6
- [Bug]: Mount happens twice on forward navigation HOT 2
- [Bug]: type errors with `exactOptionalPropertyTypes` HOT 5
- [Bug]: React-router does not work with react 18, besides using router v6.12.0 HOT 1
- [Bug]: ScrollRestoration doesn't restore horizontal page scroll HOT 1
- [Bug]: Component does not load for JSX-returning arrow functions HOT 1
- [Bug]: Can we check shouldRevalidation before we cancel a loader? HOT 2
- [Bug]: unstable_patchRoutesOnNavigation doesn't handle multiple click correctly while loading
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from react-router.