11

I wanna open a popin inside a route, and I wanna add an hash to the url.

For example before onClick https://www.example.com/home after onClick https://www.example.com/home#send-me-an-email

Well it works but React Router rerender the whole route.

Am I doing something wrong with React Router ? Let's see my code below (I simplified the things)

index.jsx I am using BrowserRouter like everybody

import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter as Router } from 'react-router-dom';

import App from './App';

const render = Component => {
  ReactDOM.render(
     <Router>
       <Component />
     </Router>,
    document.getElementById('root')
  );
};

render(App);

App.jsx I am using withRouter because I am gonna need history and location somewhere else

import React from 'react';
import { Route, Switch, withRouter } from 'react-router-dom';
import Header from './components/Header';
import Footer from './components/Footer';
import Home from './views/Home';


const App = ({ ...props }) => {
  return (
    <Header />
      <section>
        <Switch>
          <Route exact path={"/"} component={() => <Home {...props} />} />
          <Route path={"/home"} component={() => <Home {...props} />} />
        </Switch>
      </section>
    <Footer />
  );
};

export default withRouter(App);

Home.jsx unfortunately when I do this.props.history.push({ hash: 'send-me-an-email' }) it will rerender the route component Home, no good

...
render() {
  <div>
    <button onClick={() => this.props.history.push({ hash: 'send-me-an-email' })}>
      Send me and email
    </button>
    <Popin 
      isOpened={this.state.isPopinOpened} 
      handleClose={() => this.props.history.push({ hash: '' })} />
  </div>
}
...

How not to make a rerender just because I added a hash to te same url ? Cheers.

2
  • The only solution I can come up is to make use of shouldComponentUpdate and return false when your case matches, with this case you will tell react to not update and it sould not re-render. Commented Aug 2, 2019 at 13:41
  • 1
    No you are wrong, this is not the React Class which rerenders, it is the router which detects a new route whith a new hash a closes the old route and reopens the new one lol Commented Aug 2, 2019 at 22:22

2 Answers 2

7

Simply rely on vanilla JS:

window.history.pushState("object or string", "Title", "/home#send-me-an-email");

This will add an hash/route without rendering or reloading anything.

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

2 Comments

Your solution works fine (but it isn't detected by the hashchange listener). If you take a look at this github.com/ReactTraining/history#navigation are we talking about the same history ??
I think I am really doing right. And there is no other alternative. I am just going to use Redux to save my react state, and job is done ;)
6

I also wanted to add a #hash to the URL without triggering a re-render.

I simply used the useNavigate() hook from react-router-dom v6.

const navigate = useNavigate();
navigate('#my-fancy-hash');

Then, I read this hash with:

const { hash } = useLocation();

One thing to remember is that, at that point, the value of the hash variable would include the # character. When I had to actually use it, I simply stripped it out with:

hash.slice(1)

That should give you the proper value. I hope it helps!

1 Comment

Is there a way to keep query parameters? It turns site.com/page?query=searh to site.com/page#my-fancy-hash

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.