Gatsby: location search or hash update cannot trigger page re-render

Created on 25 Dec 2017  Â·  5Comments  Â·  Source: gatsbyjs/gatsby

I noticed location search or hash updates without pathname change won't trigger the page re-render.

I used 3 different ways to update the location from /app to /app?abc=def#test

  • navigateTo
  • Link from gatsby-link
  • this.props.history.push

and I cannot have any updated props.location in layout/index.jsx or page/app.jsx

after a little research, I found the issue is in
https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby/cache-dir/component-renderer.js#L42
the ComponentRenderer will only save new location with changed pathname into the new state so that shouldComponentUpdate can return true

Is this expected? Any reasons to ignore location search or hash change?

I can simply fix it by adding another else if case to check other location attributes, like

if (this.state.location.pathname !== nextProps.location.pathname) {
  // same here
} else if (this.state.location.key !== nextProps.location.key) {
  this.setState({
     location: nextProps.location
  })
}

Most helpful comment

I'd like to reopen this discussion. The design decision to not pass the updated location down to Route components inhibits the ability to do some client-side state toggling correctly; think widgets that have toggled states — navigation menus, modals, etc. Those should still work with the browser back and forward buttons to maintain fundamental browser UX.

By not updating the location to Route components when the pathname doesn't change, there's no way to toggle elements using URL-related state. You can't use the hash, search, or state properties of a location; none of them cause the page to re-render on the client currently.

My current use case is that I want a nav menu to open with a hash of #nav. It could be at /#nav, or /foo#nav. Not seeing any way to do this without getting into the internals. The client-side routes section of the docs is for a different use case.

All 5 comments

This is deliberate. Gatsby is a static site generator which means we need to be able serve static page versions of URLs. There's no way to (universally) serve different files for various locations. So either use pathnames or setup client only routes which can easily handle this https://www.gatsbyjs.org/docs/creating-and-modifying-pages/#creating-client-only-routes

@KyleAMathews thx for reply

we need to be able serve static page versions of URLs
I understand this, so search is definitely not appropriate for Gatsby here

but how about hash?
hash won't impact any static file server, and is supposed to be handled in client,
which means we could still serve the same file no matter what hash is given

what I want to do is using hash in componentWillReceiveProps to do something in client
say highlight different sections of pages/app.jsx by /app#section-1 /app#section-2

It's fine for client side adjustments but everyone will need to render the same initial page.

@KyleAMathews sure, if i want to have different initial pages, i will directly use pathname as u suggested: pages/app/section-1.jsx and pages/app/section-2.jsx

I wish to use 1 initial page pages/app.jsx because I only rely on section-x to do a little style tweak for the same contents. so i feel hash is more straightforward.

i may achieve it by onRouteUpdate in gatsby-browser and i will also have a look of creating-client-only-routes

but still, I am wondering if there are any real drawbacks to allow re-render page when hash changes.
Thanks for your help

I'd like to reopen this discussion. The design decision to not pass the updated location down to Route components inhibits the ability to do some client-side state toggling correctly; think widgets that have toggled states — navigation menus, modals, etc. Those should still work with the browser back and forward buttons to maintain fundamental browser UX.

By not updating the location to Route components when the pathname doesn't change, there's no way to toggle elements using URL-related state. You can't use the hash, search, or state properties of a location; none of them cause the page to re-render on the client currently.

My current use case is that I want a nav menu to open with a hash of #nav. It could be at /#nav, or /foo#nav. Not seeing any way to do this without getting into the internals. The client-side routes section of the docs is for a different use case.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

magicly picture magicly  Â·  3Comments

theduke picture theduke  Â·  3Comments

timbrandin picture timbrandin  Â·  3Comments

dustinhorton picture dustinhorton  Â·  3Comments

ferMartz picture ferMartz  Â·  3Comments