remix-run / react-router

Declarative routing for React
https://reactrouter.com
MIT License
52.76k stars 10.21k forks source link

[Bug]: Navigation from '//' pathname does not work; path '*' is not matching the '//' page #11429

Open MateuszGroth opened 5 months ago

MateuszGroth commented 5 months ago

What version of React Router are you using?

6.22.3

Steps to Reproduce

Case 1 - Create a router to test * path

<Route
    path="/"
    element={<Outlet />}
  >
     <Route path="*" element={<>Test * Path</>} />
</Route>

Case 2 - Create a router to test 'navigate'

const TestNavigate = () => {
  const navigate = useNavigate();

  useEffect(() => {
    navigate("/test");
  }, [navigate]);

  return <Outlet />;
};

<Route path="/" element={<TestNavigate />}>
    <Route path="*" element={<>Test</>} />
</Route>

Enter the app with '//' path on either case

Expected Behavior

Case 1 - Test * Path should be rendered Case 2 - navigate should work

Actual Behavior

Case 1 - nothing is rendered Case 2 - navigate doesn't work with the following error: TypeError: Failed to construct 'URL': Invalid URL

simPod commented 4 months ago

Same here. IMO, there's no clean way to handle the error right now.

I tried wrapping in try catch but it does not seem to catch it.

hjonasson commented 4 months ago

This is a URL specification "issue" and not a Remix one.

A path-relative-URL string must be zero or more URL-path-segment strings, separated from each other by U+002F (/), and not start with U+002F (/).

from here

simPod commented 4 months ago

But nobody said it's Remix 🤔

Adding a stacktrace, it's missing here:

router.js:425 Uncaught (in promise) TypeError: Failed to construct 'URL': Invalid URL
    at Object.createURL (router.js:425:1)
    at createClientSideRequest (router.js:3905:1)
    at startNavigation (router.js:1882:1)
    at Object.initialize (router.js:1550:1)
    at createBrowserRouter (index.js:243:4)
    at reactrouterv6.js:347:1
jpiazzal commented 2 months ago

I have a little workaround, it's not really clean code but for now it works waiting for the issue to be fixed.

Add this in your main.tsx

const doubleSlashRegexp = new RegExp('^//+', 'g');

if (doubleSlashRegexp.test(window.location.pathname)) {
  window.location.pathname = window.location.pathname.replaceAll(doubleSlashRegexp, '/');
}