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

useFetcher: request.url references fetcher url for resource routes. #5328

Closed
1 task done
dT-Nick opened this issue Jan 31, 2023 · 3 comments
Closed
1 task done

useFetcher: request.url references fetcher url for resource routes. #5328

dT-Nick opened this issue Jan 31, 2023 · 3 comments

Comments

@dT-Nick
Copy link

dT-Nick commented Jan 31, 2023

What version of Remix are you using?

1.12.0

Are all your remix dependencies & dev-dependencies using the same version?

  • Yes

Steps to Reproduce

Kind of a follow up to #5091. Add a useFetcher to a route, create a resource route for that fetcher to load data from. Inside of the resource routes loader function, request.url is the url of the fetcher, not the active location/route a user is making the request from, and request.headers.get('referer') is a active url before the revalidation has taken place (i.e. it doesn't include the changes).

Expected Behavior

In line with #5091, like currentUrl and currentParams in the shouldRevalidate function now referencing the active location (an update a part of 1.12.0 I believe). I think that request.url in a resource route should also follow that same thinking. For my use case I need to be able to get the query params from within the resource routes loader - the only other way I can see is using the referer header, but that shows the previous URL before the search params changed (perhaps that's the actual bug here).

Actual Behavior

Currently the request.url just shows the url of the resource route, and the referer url references the old URL before whatever changes happened to revalidate the fetcher.

e.g.

// active route at routes/app
// fetcher route at routes/resource-route

// user does something to add query param ?param=true

// routes/resource-route loader during revalidation
export async function loader({ request }: LoaderArgs) {
  const url = new URL(request.headers.get('referer'))
  console.log(url) // http://localhost:3000/app
  console.log(request.url) // http://localhost:3000/resource-route
  // No way to retrieve ?param=true until next revalidation cycle
  // which could even be due to removal of said search param
  
  // ...
}

I understand the search params could be added to the fetcher but that would bypass the resource routes shouldRevalidate logic and any revalidation logic would have to exist wherever the fetcher.load is being called.

@brophdawg11
Copy link
Contributor

This is expected behavior. loader's always reflect the URL being loaded, not the URL you are on. Otherwise, resource routes would be much less useful since they would be tightly coupled to the current URL you're on. For example, if you were on the homepage, you wouldn't be able to fetcher.load("/api/cart?userId=xxx") since the /api/cart loader would only receive / as the request.url.

shouldRevalidate is different because it's asking if it should re-call loaders due to a navigational change, so it provides the previous and new navigation locations from the navigation.

Can you provide an explanation of your use case here? This feels like a case where you want to actively re-call the fetcher based on certain search params changing which feels like something you'd be able to wire up via an useEffect using useLocation or useSearchParams.

@dT-Nick
Copy link
Author

dT-Nick commented Jan 31, 2023

@brophdawg11 Using useEffect and useSearchParams is what I'm doing right now. I guess the idea I was thinking was I could use shouldRevalidate to handle all of that logic instead of sticking it into a useEffect. Kind of an attempt to abstract that logic and avoid code duplication if I'm using the same resource route in multiple places - worst case scenario I can abstract that logic into a function anyway if I need to and use that function in the various useEffects, just feeling like keeping that logic within the resource route itself makes more sense to me.

I kind of figured needing the fetcher's URL may be the case. What about the referer header from the request object in this case? Shouldn't that be the new active URL with the search param changes? Again I just feel like if we're revalidating based on the active URL/params in shouldRevalidate, we should be able to at least access that same URL & params when the loader is actually revalidating. Probably a bit of an opinion-based argument, so not really worried either way if I have to do it all within the useEffect.

@brophdawg11
Copy link
Contributor

I don't think Referer is quite what you want here, since that represents the page you are coming from in traditional MPA apps, so it functions mostly the same in a RR 6.4+ SPA since we fetch data prior to updating the URL to keep the URL in sync with the displayed UI (except for popstate events where we have no choice but to fetch after it's been updated).

It sounds like you're looking for something different so you can change the behavior of a resource route loader based on the next location it's being called for. I do think this is something that can be made into a utility in user-land so would love to see what you come up with. But if you have a specific case where this is insufficient feel free to write up a proposal for consideration over in React Router (all the fetcher code lives there now).

@brophdawg11 brophdawg11 closed this as not planned Won't fix, can't repro, duplicate, stale Jan 31, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants