77

With react router I have done this up update the url:

this.props.history.push({
            pathname: `/product/${this.props.product.id}`,
        });

However this causes a re-render/navigation change. Is there a way to update the url without doing that?

My use case is I have a list of products and when I click on one I show a Modal and want to update the url to something like example.com/product/1 so that the link is sharable.

strangeQuirks
  • 4,761
  • 9
  • 40
  • 67
  • 2
    This is all built into react-router; it's called [dynamic routing](https://reacttraining.com/react-router/core/guides/philosophy) –  Jul 18 '19 at 20:06
  • 1
    i don't believe this is currently possible in react-router v6, there is an open issue: https://github.com/remix-run/react-router/issues/8908 – spatialaustin Jul 28 '22 at 19:13

3 Answers3

86

Wasn't able to find a solution using React Router, but was able to accomplish this using the browser's history interface by calling:

window.history.replaceState(null, "New Page Title", "/pathname/goes/here")

You can learn more about .replaceState here.

React Router's history.replace won't always work

React Router's history.replace method may or may not trigger a re-render depending on your app's route setup (e.g., you have a catch-all /* route). It does not prevent a render by definition.

Adrian Maseda
  • 896
  • 6
  • 7
  • 13
    Beware that this change might bypass React Router's knowledge of the current path if it is again modified later. E.G. if you append 1 sub path using this method and then use RR to navigate up 1 level, it will visually jump 2 because RR still thinks the location is without the appended sub path. – Magnus Bull Jan 26 '21 at 10:13
  • I had the exact same issue as the OP and solved it using his approach. Many thanks! @MagnusBull for browser history I simply use `window.history.pushState(stringify(currentParams), "");` and that seems to do the trick though I haven't encountered the sub path issue you spoke about – Sangeet Agarwal Mar 15 '21 at 17:48
  • 2
    @usr28765526 My point is that if you use React Router to handle navigation, then using the browser API `replaceState` can be considered a "hack" and RR will not know that the path changed. If you try to use React Router's `location` after the URL has been modified, it will operate on the version of the URL it knows about: The one before the change. This can be unpredictable and confusing. – Magnus Bull Mar 16 '21 at 18:37
  • So helpful, thank you! Did not know history.replace could cause re-renders – Katie Fedoseeva Sep 26 '22 at 23:50
9

replace will override the URL

this.props.history.replace({ pathname: `/product/${this.props.product.id}`})
AngelSalazar
  • 3,080
  • 1
  • 16
  • 22
-3

I'm using a nice way of tricking the users that's the URL doesn't change.

To do this, you'll just need to setup your routes like this.

const Home = '/';
const About = '/ ';
const Contact = '/  ';

Notice the spaces. All characters will be counted inside the quote so it should work.

Routes.tsx

<Route exact path={Home} component={Home} />
<Route exact path={About} component={About} />
<Route exact path={Contact} component={Contact} />

Inside your About.tsx and Contact.tsx:

  useEffect(() => {
    window.history.replaceState(null, '', Home);
  }, []);

After the user navigates to About or Contact pages, the hook will be called and run the code inside the callback function. It will remove the spaces after the component rendered.

That should be clean trick to disguise hidden URL

  • 1
    This is basically the Whitespace version of URLs https://en.wikipedia.org/wiki/Whitespace_(programming_language) – Renato Gama Mar 16 '23 at 06:27
  • unlike any other answer, you'll notice a sec within a flicker everytime location changes. my client hated that one as well so i used a trick. consider my answer above a – Nivek Mozart Mar 17 '23 at 22:02
  • @NivekMozart The problem with this code is that it drastically reduces readability and greatly enhances the chances of human error. You can stop flickering without playing whitespace golf. – aggregate1166877 Jun 11 '23 at 22:59