Git Product home page Git Product logo

Comments (8)

david-crespo avatar david-crespo commented on September 27, 2024 1

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.

kiliman avatar kiliman commented on September 27, 2024

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.

david-crespo avatar david-crespo commented on September 27, 2024

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.

kiliman avatar kiliman commented on September 27, 2024

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 using history.replaceState instead of history.pushState.

from react-router.

brophdawg11 avatar brophdawg11 commented on September 27, 2024

@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?

Screenshot 2024-08-08 at 3 12 31 PM

from react-router.

brophdawg11 avatar brophdawg11 commented on September 27, 2024

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.

david-crespo avatar david-crespo commented on September 27, 2024

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.

brophdawg11 avatar brophdawg11 commented on September 27, 2024

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)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.