react-router: How do I update the url without causing a navigation/reload?

JavascriptReactjsReact Router

Javascript Problem Overview


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.

Javascript Solutions


Solution 1 - Javascript

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.

Solution 2 - Javascript

replace will override the URL

this.props.history.replace({ pathname: `/product/${this.props.product.id}`})

Solution 3 - Javascript

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 

Solution 4 - Javascript

When you're inside a react component, the props has history, you can use that.

For those who are looking for a way to navigate even when not inside a react component, i.e., you can't get the props.history, this is one way to do it:

In the component where you render the router:

// outside the component
export const browserRouterRef = React.createRef();

// on render
<BrowserRouter ref={browserRouterRef}>

Then you can import browserRouterRef anywhere and use browserRouterRef.current.history to change the route even if you are not inside a react component.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionstrangeQuirksView Question on Stackoverflow
Solution 1 - JavascriptAdrian MasedaView Answer on Stackoverflow
Solution 2 - JavascriptAngelSalazarView Answer on Stackoverflow
Solution 3 - JavascriptNivek MozartView Answer on Stackoverflow
Solution 4 - JavascriptaprilmintacpinedaView Answer on Stackoverflow