2

I want to remove the # Hash from the url using React Router dom. I came across the solution of putting the browserrouter around the switch with the routes, which seems to only work when you change between tabs, but when reloading or loading the site initially the # still appears

My Router Code

return (
<BrowserRouter>
<Switch>
  {!authCtx.isLoggedIn && (
    <Route
      exact
      path="/"
      component={() => (
            <Home />
      )}
    />
  )}
  {!authCtx.isLoggedIn && (
    <Route path="/Login" component={() => <Login />} />
  )}
  {authCtx.isLoggedIn && (
    <Route
      path="/EmployeeHome"
      component={() => (
          <EmployeeHome />
      )}
    />
  )}
  {authCtx.isLoggedIn && (
    <Route path="/Appointment">
      <Redirect to="/EmployeeHome" />
    </Route>
  )}
  {authCtx.isLoggedIn && (
    <Route path="/Documentations" component={() => <Documentations />} />
  )}
  {authCtx.isLoggedIn && (
    <Route
      path="/Statistic"
      component={() => (
          <Statistics />
      )}
    />
  )}

  <Route path="*">
    {authCtx.isLoggedIn && <Redirect to="/Appointment" />}
    {!authCtx.isLoggedIn && <Redirect to="/" />}
  </Route>
</Switch>
</BrowserRouter>);
4
  • 1
    What version are you using? I haven't seen hashes in a React app for years. Commented Feb 25, 2022 at 15:00
  • Using ^16.0.0. Can I just upgrade it? Commented Feb 25, 2022 at 15:16
  • Is your app using a HashRouter? If so, then don't use a HashRouter, use one of the other high-level routers, e.g. BrowserRouter. Also, if you are using more than one router, don't. You really only need one router near the root of your app to provide a routing context for all routing/navigation components/hooks/etc... Remove all extraneous routers. You're using RRDv5 it seems, which allows you to nest routers, but it isn't recommended, and actually throws an invariant error in later version. Can you update your question to include all relevant routing & navigation code? Commented Feb 25, 2022 at 16:47
  • @isherwood nothing wrong with using hashrouter. Definitely preferred in situations where it's hard to do server-side url rewriting. Commented Nov 23, 2023 at 0:51

4 Answers 4

6
if(window.location.hash) {
     window.history.replaceState("", document.title, window.location.pathname);
}

Before

site.url/home#section

After

site.url/home

Sign up to request clarification or add additional context in comments.

2 Comments

Clever hack. Downvoted for use of window which will fail in SSR context.
The question did not indicate that SSR is a concern, though.
4

My problem was that I was using a HashRouter and also a react-router-dom version <=6.0. I updated everything and changed to the v6 of the react-router-dom and used the BrowserRouter instead and now it works.

Here is my Code:

React Router

<Routes>
  {!authCtx.isLoggedIn && (
    <Route
      exact
      path="/"
      element={
            <Home />
      }
    />
  )}
  {!authCtx.isLoggedIn && <Route path="/Login" exact element={<Login />} />}
  {authCtx.isLoggedIn && (
    <Route
      exact
      path="/EmployeeHome"
      element={
          <EmployeeHome />
      }
    />
  )}
  {authCtx.isLoggedIn && (
    <Route
      exact
      path="/Documentations"
      element={ <Documentations />}
    />
  )}
  {authCtx.isLoggedIn && (
    <Route
      exact
      path="/Statistic"
      element={
          <Statistics />
      }
    />
  )}
  {authCtx.isLoggedIn && (
    <Route path="*" element={<Navigate to="/EmployeeHome" />} />
  )}
  {!authCtx.isLoggedIn && <Route path="*" element={<Navigate to="/" />} />}
</Routes>

Index.js

const baseUrl = document.getElementsByTagName("base") 
[0].getAttribute("href");
const rootElement = document.getElementById("root");

ReactDOM.render(
    <BrowserRouter basename={baseUrl}>
      <App />
    </BrowserRouter>,
rootElement
);

1 Comment

You can also use different routes instances for sections like #Home or just by short some text from url browser bar.
3

From all of the above the simplest solution is to navigate back to #, like this

navigate('#');

This way it won't change your URL and query params and it will allow you to reset the hash.

NB make sure to use useNavigate from react-router-dom in order to use the navigate function

1 Comment

Worth noting, this will totally remove the hash, so you won't have a /# in your URL.
1

I mean you can interpret "is working now" as a favourable way to you, but indeed, these are different oriented instances from React components:

<HashRouter>

 A <Router> that uses the hash portion of the URL (i.e. window.location.hash) to keep your UI in sync with the URL.

const baseUrl = document.getElementsByTagName("base") 
[0].getAttribute("href");
const rootElement = document.getElementById("root");

ReactDOM.render(
  <HashRouter
    basename={baseUrl}
    getUserConfirmation={optionalFunc}
    hashType={optionalString}>
    <App />
  </HashRouter>,
rootElement
);

<BrowserRouter>

 A <Router> that uses the HTML5 history API (pushState, replaceState and the popstate event) to keep your UI in sync with the URL.

const baseUrl = document.getElementsByTagName("base") 
[0].getAttribute("href");
const rootElement = document.getElementById("root");

ReactDOM.render(
<BrowserRouter
  basename={baseUrl}
  forceRefresh={optionalBool}
  getUserConfirmation={optionalFunc}
  keyLength={optionalNumber}>
  <App />
</BrowserRouter>,
rootElement
);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.