reactjsreact-routerreact-router-dombasename

React Hash Router v6 with basename


I need to use a hash router with a basename. I did this with the createHashRouter (React Router 6.8), with the basename property to render the app in the sub-route. When I open /sub/route in the browser I get the empty page though, only css background is visible.

All of the files and assets are shipped to the app, but the JS is not executed and the root div stays empty.

The code of the Router:

const router = createHashRouter([
   {
      id: 'root',
      path: '/',
      element: <App />,
      errorElement: <ErrorPage />,
      loader: filtersLoader(queryClient),
      children: [
         { path: '/', element: <Navigate to="/dashboard/performance" /> },
         {
            path: '/dashboard',
            id: 'dashboard',
            errorElement: <ErrorPage />,
            loader: dataLoader(queryClient),
            element: (
               <>
                  <Header />
                  <Outlet />
               </>
            ),
            children: [
               { index: true, element: <Index /> }
            ]
         },
         {
            path: 'info',
            element: <Info />
         }
      ]
   }
], {
   basename: '/sub/route'
});

Update/solution

the issue was caused by mixing HashRouter with basename. Getting rid of the basename in createHashRouter solved the issue.


Solution

  • The HashRouter will basically already just work from whatever directory you deploy/serve the React app from, specifying a basename doesn't make as much since here as it does for the BrowserRouter where the routes/links need it as part of their resolved paths.

    The <Router basename> prop may be used to make all routes and links in your app relative to a "base" portion of the URL pathname that they all share. This is useful when rendering only a portion of a larger app with React Router or when your app has multiple entry points. Basenames are not case-sensitive.

    The HashRouter uses the URL hash for routing, so for example if you add that one has a basename="/sub/route" then you are specifying that all routes and links operate relative to it where it's rendered. If the app is hosted/served from "https://www.example.com/subA/subB" then you are effectively saying "https://www.example.com/subA/subB/#/sub/route" is where the app is running and the browser will need to be navigated to this URL to start the proper routing.

    If "/sub/route" is already where the app is hosted/served from then there's nothing to set as a basename if you want to keep the default behavior of routing/linking relative to a "/" path on "https://www.example.com/sub/route/#/".

    Remove the basename property from the routing configuration.

    const router = createHashRouter([
       {
          id: 'root',
          path: '/',
          element: <App />,
          errorElement: <ErrorPage />,
          loader: filtersLoader(queryClient),
          children: [
             { path: '/', element: <Navigate to="/dashboard/performance" /> },
             {
                path: '/dashboard',
                id: 'dashboard',
                errorElement: <ErrorPage />,
                loader: dataLoader(queryClient),
                element: (
                   <>
                      <Header />
                      <Outlet />
                   </>
                ),
                children: [
                   { index: true, element: <Index /> }
                ]
             },
             {
                path: 'info',
                element: <Info />
             }
          ]
       }
    ]);