Gatsby: Client side only paths do not update dom properly on direct linking

Created on 25 Sep 2019  路  21Comments  路  Source: gatsbyjs/gatsby

Description

When you use client only paths, if you refresh on any client only page the dom isn't properly updated. It causes the dom from the initial root page to stick around and breaks the other client side pages. This does not happen locally, but it happens in production environments both on netlify and s3/cloudfront

I noticed this on my own project, where going directly to a client side route was adding the component into my root client side route's structure.

So something like

// app/login
<div class="container">
  <h1>Login</h1>
</div>

and another component like

// app/profile
<div class="different-container">
  <h2>Profile</h2>
</div>

But instead in the browser I see

<div class="container">
  <div class="different-container">
    <h2>Profile</h2>
  </div>
</div>

I am unable to reproduce using npm run build && npm run serve locally

Steps to reproduce

Go to the example https://client-only-paths.gatsbyjs.org/ click on any other page that is not the 1st page. Then click refresh. You will see that the background color is not the correct color but is instead the background color for page 1

You can also go directly to https://client-only-paths.gatsbyjs.org/page/4 and see that the background color is that of page 1 instead of purple like it should be

Expected result

The background color should be the appropriate color for the page.

Actual result

The background color is incorrect

Environment

stale? bug

Most helpful comment

I cloned from https://github.com/gatsbyjs/gatsby/blob/master/examples/client-only-paths and that was the only modification I made.

What your example is missing is gatsby-plugin-netlify to handle redirect from /sample/* to /sample/. Without this, the 404 page is temporarily shown, causing the flash.

All 21 comments

I have a similar problem. Here the link target for an internal-to-this-site page, is incorrect.

  • Only fails when deployed to a site where the pathPrefix is being used (I deploy to a github pages site)

  • Failure: the link target has an extra path element (of the page being linked from). E.g., if the page where the link is, is:
    pages.github..../some-org/some-repo/from-page,
    the link (seen by hovering, and also clicking) should be:
    pages.github..../some-org/some-repo/to-page,
    but if you hit "refresh" on the from-page, (or initially), the link is instead:
    pages.github..../some-org/some-repo/from-page/to-page,

This (in my case) can be "fixed" by using the left-hand-navigation (which my site has) to select a different page, and then selecting the the original from-page from the left-hand-navigation: now the links are correct. Note that just using the browser "back" button isn't sufficient to fix this.

Same issue here, did you solve it?.

two workarounds. #1: when specifying client-side-only path to a page in a link, only use forms starting from the "top" of the website, with urls that look like /pathPart1/pathPart2 etc. Don't use ../ kinds of path specs.

Fix #2: I was using gatsby-theme-carbon's

As you can see in the example: https://client-only-paths.gatsbyjs.org/page/4 first it shows 1 and then 4 that's the issue do you guys have any workarounds?.

Pd: it happens when you reload too.

It looks like the example has been taken down, would love to get some feedback on this bug and see if anyone has any insight into why?

It seems to be a hydration problem. There's a mismatch between the server-rendered output and the actual client-only output.

For now a temporary workaround is disabling server-rendering on those client-only paths.

// https://github.com/gatsbyjs/gatsby/blob/master/examples/client-only-paths/src/pages/index.js

...
export default props => {
  if (typeof window === 'undefined') return null
  return <App {...props} />
}

Can check out the examples here:
original https://buggy-client-only-paths.netlify.com/page/3
with workaround https://non-buggy-client-only-paths.netlify.com/page/3

It seems to be a hydration problem. There's a mismatch between the server-rendered output and the actual client-only output.

For now a temporary workaround is disabling server-rendering on those client-only paths.

// https://github.com/gatsbyjs/gatsby/blob/master/examples/client-only-paths/src/pages/index.js

...
export default props => {
  if (typeof window === 'undefined') return null
  return <App {...props} />
}

Can check out the examples here:
original https://buggy-client-only-paths.netlify.com/page/3
with workaround https://non-buggy-client-only-paths.netlify.com/page/3

Thanks for sharing this. I tried to use the workaround you mentioned but I'm not able to fix this.
You can see a minimal repo here: https://codesandbox.io/s/gatsby-starter-default-7nv3l
correct styles: https://csb-7nv3l.netlify.com/sample/
incorrect styles: https://csb-7nv3l.netlify.com/sample/11

can you share code repo for https://non-buggy-client-only-paths.netlify.com/page/3 ?

I cloned from https://github.com/gatsbyjs/gatsby/blob/master/examples/client-only-paths and that was the only modification I made.

What your example is missing is gatsby-plugin-netlify to handle redirect from /sample/* to /sample/. Without this, the 404 page is temporarily shown, causing the flash.

Thank you, I added gatsby-plugin-netlify and the problem is fixed now for the demo site.
However, my actual site which is not hosted on netlify needs to be fixed.

Which hosting service are you using?

I'm deploying my gatsby site as a static app on AWS with caprover

this ngnix config file in caprover's deployment fixed it for the codebox's sample

server {
  listen 80;

  location / {
    root   /usr/share/nginx/html;
    index  index.html index.htm;
    try_files $uri $uri/ /index.html;
  }

  location /sample {
    root   /usr/share/nginx/html;
    index  index.html index.htm;
    try_files $uri $uri/ /sample/index.html;
  }

  error_page   500 502 503 504  /50x.html;
  location = /50x.html {
    root   /usr/share/nginx/html;
  }
}

I'm not 100% sure if I follow the issue here. I feel like it's a misconfiguration more than a gatsby issue.

@wardpeet if you look at this post by @universse https://github.com/gatsbyjs/gatsby/issues/17891#issuecomment-548660698 he says it's a hydration problem with Gatsby. Once you fix the Hydration problem using the code he gives (and assuming you have configured your redirects correctly), he was able to get it working

If there is no plan to fix this in the short term, maybe there should be some documentation on this fix for the hydration problem? Or at least an update to the example repo https://github.com/gatsbyjs/gatsby/tree/master/examples/client-only-paths

This seems to be related to this React 16 SSR issue https://github.com/facebook/react/issues/10591 . I doubt if it can be fixed from Gatsby side.

We also get this issue, and it's really frustrating 馃槩 Managed to workaround it by basically rendering nothing for the 404 page, if the window object is not present, as others have suggested.

This does work, but now we can't have a statically rendered 404 page and it feels quite hacky to me to be used in production.

@wardpeet - Do you know what the misconfiguration would be in this case? I've seen a number of comments like yours on all the various issues surrounding this, but I'm struggling to find what I need to put in place, to stop this from happening on AWS. We use gatsby-plugin-create-client-paths as suggested and gatsby-plugin-s3.

My understanding was that if we are defining these client paths properly, then gatsby-plugin-s3 should setup the redirects for us on S3/Amazon. But given this issue, it appears that is not the case at all. Is there something else I should be adding to amazon that's not handled by the plugin? Because if there is, I'm not finding anything in the documentation / online.

Also @jrusso1020 - You mentioned that you can't reproduce this locally when using npm run serve. This is correct, and I've experienced the same. But, if you use the (confusingly named, in this context) package on NPM called serve you should be able to recreate this locally.

// Make sure you're in your gatsby project
// Install the NPM package
npm install -g serve
serve -p 9999 public
// Server should now be running at localhost:9999 and you should be able to reproduce this error

Hiya!

This issue has gone quiet. Spooky quiet. 馃懟

We get a lot of issues, so we currently close issues after 30 days of inactivity. It鈥檚 been at least 20 days since the last update here.
If we missed this issue or if you want to keep it open, please reply here. You can also add the label "not stale" to keep this issue open!
As a friendly reminder: the best way to see this issue, or any other, fixed is to open a Pull Request. Check out gatsby.dev/contribute for more information about opening PRs, triaging issues, and contributing!

Thanks for being a part of the Gatsby community! 馃挭馃挏

Hey again!

It鈥檚 been 30 days since anything happened on this issue, so our friendly neighborhood robot (that鈥檚 me!) is going to close it.
Please keep in mind that I鈥檓 only a robot, so if I鈥檝e closed this issue in error, I鈥檓 HUMAN_EMOTION_SORRY. Please feel free to reopen this issue or create a new one if you need anything else.
As a friendly reminder: the best way to see this issue, or any other, fixed is to open a Pull Request. Check out gatsby.dev/contribute for more information about opening PRs, triaging issues, and contributing!

Thanks again for being part of the Gatsby community! 馃挭馃挏

We also get this issue, and it's really frustrating 馃槩 Managed to workaround it by basically rendering nothing for the 404 page, if the window object is not present, as others have suggested.

This does work, but now we can't have a statically rendered 404 page and it feels quite hacky to me to be used in production.

@wardpeet - Do you know what the misconfiguration would be in this case? I've seen a number of comments like yours on all the various issues surrounding this, but I'm struggling to find what I need to put in place, to stop this from happening on AWS. We use gatsby-plugin-create-client-paths as suggested and gatsby-plugin-s3.

My understanding was that if we are defining these client paths properly, then gatsby-plugin-s3 should setup the redirects for us on S3/Amazon. But given this issue, it appears that is not the case at all. Is there something else I should be adding to amazon that's not handled by the plugin? Because if there is, I'm not finding anything in the documentation / online.

Can you show me an example of a site failing? I don't think I understand the issue completely.

@wardpeet - We haven't got a version of the site running publically at the moment, as we are still in development. But I'll describe the issue as best I can:

We use gatsby to build a lot of static pages, but we also have some dynamic pages. When navigating to these dynamic pages (/jobs/123), the 404 page would flash onto the screen, for around a second, before the JS kicked in and gatsby renders the actual page you're looking for.

Ideally, I'd expect in this case that we can build a file called jobs.html as a catch all for /jobs/* that just contains the loading state for the page and that would be statically rendered, like every other page.

The workaround in this case was to add const browser = typeof window !== 'undefined' && window and only render our Not found page, when that constant is truthy. This is odd, but softens the impact of this problem a bit.

It's hacky and horrible, because it's still rendering the 404 page, it's just the 404 component itself is returning nothing so the user sees a blank screen. This means that although we've correctly setup loading states for those pages, a majority of the loading is just a blank screen which is unhelpful from a user perspective. These pages are now not statically rendered and we lose one of the biggest benefits of using gatsby for a large chunk of our site.

If any of that doesn't make sense please let me know. I'm trying to recall after a long christmas break 馃槃 . If needed, I can try and get an app running publically, that illustrates the problem a bit better

(It's worth noting, that this problem is only present when a user specifically loads the page for the first time, or hits the refresh button. Navigating from our homepage -> a dynamic page using the gatsby-link component works fine. But we see a 404 page on refresh)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

dustinhorton picture dustinhorton  路  3Comments

andykais picture andykais  路  3Comments

brandonmp picture brandonmp  路  3Comments

magicly picture magicly  路  3Comments

3CordGuy picture 3CordGuy  路  3Comments