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

Support use of external links when using useHref in RouterProvider #6397

Open
Niznikr opened this issue May 16, 2024 · 3 comments
Open

Support use of external links when using useHref in RouterProvider #6397

Niznikr opened this issue May 16, 2024 · 3 comments

Comments

@Niznikr
Copy link

Niznikr commented May 16, 2024

Provide a general summary of the feature here

The enhancements from #5864 have been great to support features we use from React Router. We are running into an issue though with the fact that when passing useHref to RouterProvider we lose the ability to use external links as all RAC href values get passed to useHref. It would be convenient to have a way to opt-out of useHref or detect an external link so both kinds can exist in an app.

🤔 Expected Behavior?

Set useHref in RouterProvider with React Router's version. There is a way to pass https://www.google.com to a RAC href prop and opt-out of passing it to useHref so that the final value is https://www.google.com.

😯 Current Behavior

Set useHref in RouterProvider with React Router's version. Passing https://www.google.com to a RAC href prop results in [current_url]/https://www.google.com.

💁 Possible Solution

Add an optional prop for RAC where href and routerOptions are available to opt-out of passing it through useHref or detect an external link similar to how RR does this https://github.com/remix-run/react-router/blob/main/packages/react-router-dom/index.tsx#L958-L982

🔦 Context

I want RAC links to support both client-side routing and external links simultaneously when using useHref in RouterProvider.

💻 Examples

No response

🧢 Your Company/Team

No response

🕷 Tracking Issue

No response

@LFDanLu
Copy link
Member

LFDanLu commented Jul 11, 2024

Could you wrap React Router's useHref in your own function and determine whether to return https://www.google.com or [current_url]/https://www.google.com. and pass that into RouterProvider?

@theMosaad
Copy link
Contributor

theMosaad commented Jul 29, 2024

For anyone coming here looking for a copy-pastable solution

function useAbsoluteHref(path: string) {
  const relative = useHref(path);
  if (
    path.startsWith("https://") ||
    path.startsWith("http://") ||
    path.startsWith("mailto:")
  ) {
    return path;
  }
  return relative;
}

source: https://github.com/argos-ci/argos/blob/4822931b05c78e1b4a79e15cf4437fb0297369a6/apps/frontend/src/router.tsx#L21-L31

@evadecker
Copy link

Not the prettiest, but I was able to extend href support when using React-Aria and TanStack Router with the following:

// __root.tsx

import {
  type NavigateOptions,
  Outlet,
  type ToOptions,
  createRootRouteWithContext,
  useRouter,
} from "@tanstack/react-router";
import { RouterProvider } from "react-aria-components";

declare module "react-aria-components" {
  interface RouterConfig {
    href: ToOptions | string;
    routerOptions: Omit<NavigateOptions, keyof ToOptions>;
  }
}

export const Route = createRootRoute()({
  component: RootRoute,
});

function RootRoute() {
  const router = useRouter();

  return (
    <RouterProvider
      navigate={(path, options) =>
        router.navigate(
          typeof path === "string" ? { ...options } : { ...path, ...options },
        )
      }
      useHref={(path) =>
        typeof path === "string" ? path : router.buildLocation(path).href
      }
    >
      <Outlet />
    </RouterProvider>
  );
}

typeof path === "string" assumes an external link, while ToOptions is used for internal routing.

In your component you'd use:

// External links are strings
<Link href="https://github.com">GitHub</Link>

// Internal links are ToOptions objects
<Link href={{ to: '/about' }}>About</Link>

This supports params as well:

const myPostId = ...; // fetch param info

// Add params to your link
<Link href={{ to: '/post/$postId', { params: { postId: myPostId } }}>View Post</Link>

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

4 participants