Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(gatsby): fix not focusing router wrapper after navigation #13197

Merged
merged 26 commits into from
Jul 3, 2019
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
c783437
add probably failing test
pieh Apr 7, 2019
4379722
rename custom command to make it clear it's assertion
pieh Apr 7, 2019
571aa10
first find page, then use router + import from @reach/router/es
pieh Apr 7, 2019
d4147e4
revert grabbing @reach/router/es directly
pieh Apr 7, 2019
39a0e10
use webpack alias to use @reach/router es build for browser bundles
pieh Apr 7, 2019
d7d1e80
update snapshots to cover added id to focus wrapper
pieh Apr 7, 2019
b0818f2
Merge remote-tracking branch 'upstream/master' into reach-focus
pieh Apr 14, 2019
ac4f22e
testing
pieh Apr 14, 2019
335b3e6
Merge remote-tracking branch 'origin/master' into reach-focus
pieh May 15, 2019
b69e3df
mind blown
pieh May 15, 2019
8af2517
Merge remote-tracking branch 'origin/master' into reach-focus
pieh May 15, 2019
15740ee
use BASE_PATH and PATH_PREFIX
pieh May 15, 2019
06b3114
fix focusing on navigation from 404 to different 404, improve focus m…
pieh May 19, 2019
3ad203a
fix most of focus navigation focus managment in development
pieh May 19, 2019
30df94c
remove stray console.log
pieh May 19, 2019
2d17c03
add note about partial hydration when missing resources and hydrating
pieh May 20, 2019
6d62524
Merge remote-tracking branch 'origin/master' into reach-focus
pieh May 26, 2019
00116f6
Merge remote-tracking branch 'origin/master' into reach-focus
pieh Jun 3, 2019
f84e41e
Merge remote-tracking branch 'origin/master' into reach-focus
pieh Jun 24, 2019
5996d80
update dev runtime
pieh Jun 25, 2019
ef89046
update snapshot
pieh Jun 25, 2019
931c911
use nested route
pieh Jun 25, 2019
2868637
Merge remote-tracking branch 'origin/master' into reach-focus
pieh Jul 3, 2019
43bc8b4
add matchPath to pageResources object
pieh Jul 3, 2019
dfacf88
update snapshot
pieh Jul 3, 2019
498337e
remove stray console.log
pieh Jul 3, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
describe(`focus managment`, () => {
it(`Focus router wrapper after navigation to regular page (from index)`, () => {
cy.visit(`/`).waitForRouteChange()

cy.changeFocus()
cy.assertRouterWrapperFocus(false)
cy.navigateAndWaitForRouteChange(`/page-2/`)
cy.assertRouterWrapperFocus(true)
})

it(`Focus router wrapper after navigation to regular page (to index)`, () => {
cy.visit(`/page-2/`).waitForRouteChange()

cy.changeFocus()
cy.assertRouterWrapperFocus(false)
cy.navigateAndWaitForRouteChange(`/`)
cy.assertRouterWrapperFocus(true)
})

// Navigating to 404 and from 404 doesn't properly trigger focusing
// router wrapper. That's because dev 404 is special case and new router
// is being used when transitioning to/from 404 page and @reach/router
// doesn't meddle with focus on initial router component mount.

it.skip(`Focus router wrapper after navigation to 404`, () => {
cy.visit(`/`).waitForRouteChange()

cy.changeFocus()
cy.assertRouterWrapperFocus(false)
cy.navigateAndWaitForRouteChange(`/broken-path/`)
cy.assertRouterWrapperFocus(true)
})

it.skip(`Focus router wrapper after navigation from 404`, () => {
cy.visit(`/broken-path`, { failOnStatusCode: false }).waitForRouteChange()

cy.changeFocus()
cy.assertRouterWrapperFocus(false)
cy.navigateAndWaitForRouteChange(`/`)
cy.assertRouterWrapperFocus(true)
})

it(`Focus router wrapper after navigation from one 404 path to another 404 path`, () => {
cy.visit(`/broken-path`, { failOnStatusCode: false }).waitForRouteChange()

// navigating to different not existing page should also trigger
// router wrapper focus as this is different page
cy.changeFocus()
cy.assertRouterWrapperFocus(false)
cy.navigateAndWaitForRouteChange(`/another-broken-path/`)
cy.assertRouterWrapperFocus(true)
})

it(`Focus router wrapper after navigation to client-only page`, () => {
cy.visit(`/`).waitForRouteChange()

cy.changeFocus()
cy.assertRouterWrapperFocus(false)
cy.navigateAndWaitForRouteChange(`/client-only-paths/`)
cy.assertRouterWrapperFocus(true)
})

it(`Focus router wrapper after navigation from client-only page`, () => {
cy.visit(`/client-only-paths/`).waitForRouteChange()

cy.changeFocus()
cy.assertRouterWrapperFocus(false)
cy.navigateAndWaitForRouteChange(`/`)
cy.assertRouterWrapperFocus(true)
})

it(`Focus subrouter inside client-only page`, () => {
cy.visit(`/client-only-paths`).waitForRouteChange()

cy.changeFocus()
cy.assertRouterWrapperFocus(false)
cy.navigateAndWaitForRouteChange(`/client-only-paths/profile`)

// inner paths are handled by router instance defined in client-only-paths page
// which means that navigating inside those should be handled by that router
// (not main router provided by gatsby)
cy.assertRouterWrapperFocus(false)
cy.focused().should(`have.attr`, `id`, `client-only-paths-sub-router`)
})
})
37 changes: 37 additions & 0 deletions e2e-tests/development-runtime/cypress/support/commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,40 @@ Cypress.Commands.add(`lifecycleCallCount`, action =>
).length
)
)

Cypress.Commands.add(`assertRouterWrapperFocus`, (shouldBeFocused = true) =>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are so awesome!! 🌮

cy
.focused()
.should(
shouldBeFocused ? `have.attr` : `not.have.attr`,
`id`,
`gatsby-focus-wrapper`
)
)

Cypress.Commands.add(
`navigateAndWaitForRouteChange`,
{
prevSubject: `optional`,
},
(subject, pathname) => {
cy.window().then(win => {
win.___navigate(pathname)
})

return cy.waitForAPI(`onRouteUpdate`).then(() => subject)
}
)

Cypress.Commands.add(
`changeFocus`,
{
prevSubject: `optional`,
},
subject => {
cy.get(`a`)
.first()
.focus()
.then(() => subject)
}
)
6 changes: 4 additions & 2 deletions e2e-tests/development-runtime/gatsby-node.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,9 @@ exports.onCreatePage = async ({ page, actions }) => {

if (page.path.match(/^\/paths/)) {
page.matchPath = `/paths/*`
createPage(page)
} else if (page.path.match(/^\/client-only-paths/)) {
page.matchPath = `/client-only-paths/*`
createPage(page)
}

createPage(page)
}
4 changes: 2 additions & 2 deletions e2e-tests/development-runtime/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@
"license": "MIT",
"scripts": {
"build": "gatsby build",
"develop": "cross-env ENABLE_GATSBY_REFRESH_ENDPOINT=true gatsby develop",
"develop": "cross-env ENABLE_GATSBY_REFRESH_ENDPOINT=true CYPRESS_SUPPORT=y gatsby develop",
"serve": "gatsby serve",
"start": "npm run develop",
"format": "prettier --write \"src/**/*.js\"",
"test": "CYPRESS_SUPPORT=y npm run start-server-and-test || (npm run reset && exit 1)",
"test": "npm run start-server-and-test || (npm run reset && exit 1)",
"posttest": "npm run reset",
"reset": "node scripts/reset.js",
"reset:preview": "node plugins/gatsby-source-fake-data/reset.js && npm run update:preview",
Expand Down
38 changes: 38 additions & 0 deletions e2e-tests/development-runtime/src/pages/client-only-paths.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import React from "react"
import { Router } from "@reach/router"
import { Link } from "gatsby"

import Layout from "../components/layout"
import InstrumentPage from "../utils/instrument-page"

const Page = props => (
<pre data-testid="dom-marker">[client-only-path] {props.page}</pre>
)

const routes = [`/`, `/profile`, `/dashboard`]

const basePath = `/client-only-paths`

const ClientOnlyPathPage = props => (
<Layout>
<Router
location={props.location}
basepath={basePath}
id="client-only-paths-sub-router"
>
<Page path="/" page="index" />
<Page path="/:page" />
</Router>
<ul>
{routes.map(route => (
<li key={route}>
<Link to={`${basePath}${route}`} data-testid={route}>
{route}
</Link>
</li>
))}
</ul>
</Layout>
)

export default InstrumentPage(ClientOnlyPathPage)
2 changes: 1 addition & 1 deletion e2e-tests/development-runtime/src/pages/paths.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const NotFound = () => <h1>Not Found in App</h1>

const AppPage = () => (
<Router>
<App path="/paths/app" />
<App path="/app" />
<NotFound default />
</Router>
)
Expand Down
80 changes: 80 additions & 0 deletions e2e-tests/production-runtime/cypress/integration/accessibility.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
describe(`focus managment`, () => {
it(`Focus router wrapper after navigation to regular page (from index)`, () => {
cy.visit(`/`).waitForRouteChange()

cy.changeFocus()
cy.assertRouterWrapperFocus(false)
cy.navigateAndWaitForRouteChange(`/page-2/`)
cy.assertRouterWrapperFocus(true)
})

it(`Focus router wrapper after navigation to regular page (to index)`, () => {
cy.visit(`/page-2/`).waitForRouteChange()

cy.changeFocus()
cy.assertRouterWrapperFocus(false)
cy.navigateAndWaitForRouteChange(`/`)
cy.assertRouterWrapperFocus(true)
})

it(`Focus router wrapper after navigation to 404`, () => {
cy.visit(`/`).waitForRouteChange()

cy.changeFocus()
cy.assertRouterWrapperFocus(false)
cy.navigateAndWaitForRouteChange(`/broken-path/`)
cy.assertRouterWrapperFocus(true)
})

it(`Focus router wrapper after navigation from 404`, () => {
cy.visit(`/broken-path`, { failOnStatusCode: false }).waitForRouteChange()

cy.changeFocus()
cy.assertRouterWrapperFocus(false)
cy.navigateAndWaitForRouteChange(`/`)
cy.assertRouterWrapperFocus(true)
})

it(`Focus router wrapper after navigation from one 404 path to another 404 path`, () => {
cy.visit(`/broken-path`, { failOnStatusCode: false }).waitForRouteChange()

// navigating to different not existing page should also trigger
// router wrapper focus as this is different page
cy.changeFocus()
cy.assertRouterWrapperFocus(false)
cy.navigateAndWaitForRouteChange(`/another-broken-path/`)
cy.assertRouterWrapperFocus(true)
})

it(`Focus router wrapper after navigation to client-only page`, () => {
cy.visit(`/`).waitForRouteChange()

cy.changeFocus()
cy.assertRouterWrapperFocus(false)
cy.navigateAndWaitForRouteChange(`/client-only-paths/`)
cy.assertRouterWrapperFocus(true)
})

it(`Focus router wrapper after navigation from client-only page`, () => {
cy.visit(`/client-only-paths/`).waitForRouteChange()

cy.changeFocus()
cy.assertRouterWrapperFocus(false)
cy.navigateAndWaitForRouteChange(`/`)
cy.assertRouterWrapperFocus(true)
})

it(`Focus subrouter inside client-only page`, () => {
cy.visit(`/client-only-paths`).waitForRouteChange()

cy.changeFocus()
cy.assertRouterWrapperFocus(false)
cy.navigateAndWaitForRouteChange(`/client-only-paths/profile`)

// inner paths are handled by router instance defined in client-only-paths page
// which means that navigating inside those should be handled by that router
// (not main router provided by gatsby)
cy.assertRouterWrapperFocus(false)
cy.focused().should(`have.attr`, `id`, `client-only-paths-sub-router`)
})
})
37 changes: 37 additions & 0 deletions e2e-tests/production-runtime/cypress/support/commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,40 @@ Cypress.Commands.add(`shouldNotMatchScrollPosition`, id =>
expect(scrollPosition).not.to.be.closeTo(storedScrollPositions[id], 100)
})
)

Cypress.Commands.add(`assertRouterWrapperFocus`, (shouldBeFocused = true) =>
cy
.focused()
.should(
shouldBeFocused ? `have.attr` : `not.have.attr`,
`id`,
`gatsby-focus-wrapper`
)
)

Cypress.Commands.add(
`navigateAndWaitForRouteChange`,
{
prevSubject: `optional`,
},
(subject, pathname) => {
cy.window().then(win => {
win.___navigate(pathname)
})

return cy.waitForAPI(`onRouteUpdate`).then(() => subject)
}
)

Cypress.Commands.add(
`changeFocus`,
{
prevSubject: `optional`,
},
subject => {
cy.get(`a`)
.first()
.focus()
.then(() => subject)
}
)
6 changes: 5 additions & 1 deletion e2e-tests/production-runtime/src/pages/client-only-paths.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@ const basePath = `/client-only-paths`

const ClientOnlyPathPage = props => (
<Layout>
<Router location={props.location} basepath={basePath}>
<Router
location={props.location}
basepath={basePath}
id="client-only-paths-sub-router"
>
<Page path="/" page="index" />
<Page path="/:page" />
</Router>
Expand Down
2 changes: 1 addition & 1 deletion e2e-tests/production-runtime/src/pages/paths.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const NotFound = () => <h1>Not Found in App</h1>

const AppPage = () => (
<Router>
<App path="/paths/app" />
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sweet!

<App path="/app" />
<NotFound default />
</Router>
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ exports[`develop-static-entry onPreRenderHTML can be used to replace postBodyCom

exports[`develop-static-entry onPreRenderHTML can be used to replace preBodyComponents 1`] = `"<!DOCTYPE html><html><head><meta charSet=\\"utf-8\\"/><meta http-equiv=\\"x-ua-compatible\\" content=\\"ie=edge\\"/><meta name=\\"viewport\\" content=\\"width=device-width, initial-scale=1, shrink-to-fit=no\\"/><script src=\\"/socket.io/socket.io.js\\"></script></head><body><div> div3 </div><div> div2 </div><div> div1 </div><noscript id=\\"gatsby-noscript\\">This app works best with JavaScript enabled.</noscript><div id=\\"___gatsby\\"></div><script src=\\"/commons.js\\"></script></body></html>"`;

exports[`static-entry onPreRenderHTML can be used to replace headComponents 1`] = `"<!DOCTYPE html><html><head><meta charSet=\\"utf-8\\"/><meta http-equiv=\\"x-ua-compatible\\" content=\\"ie=edge\\"/><meta name=\\"viewport\\" content=\\"width=device-width, initial-scale=1, shrink-to-fit=no\\"/><link as=\\"fetch\\" rel=\\"preload\\" href=\\"/page-data/about/page-data.json\\" crossorigin=\\"use-credentials\\"/><style> .style3 </style><style> .style2 </style><style> .style1 </style><meta name=\\"generator\\" content=\\"Gatsby 2.0.0\\"/></head><body><noscript id=\\"gatsby-noscript\\">This app works best with JavaScript enabled.</noscript><div id=\\"___gatsby\\"><div style=\\"outline:none\\" tabindex=\\"-1\\" role=\\"group\\"></div></div><script id=\\"gatsby-script-loader\\">/*<![CDATA[*/window.pagePath=\\"/about/\\";window.webpackCompilationHash=\\"1234567890abcdef1234\\";/*]]>*/</script><script id=\\"gatsby-chunk-mapping\\">/*<![CDATA[*/window.___chunkMapping={};/*]]>*/</script></body></html>"`;
exports[`static-entry onPreRenderHTML can be used to replace headComponents 1`] = `"<!DOCTYPE html><html><head><meta charSet=\\"utf-8\\"/><meta http-equiv=\\"x-ua-compatible\\" content=\\"ie=edge\\"/><meta name=\\"viewport\\" content=\\"width=device-width, initial-scale=1, shrink-to-fit=no\\"/><link as=\\"fetch\\" rel=\\"preload\\" href=\\"/page-data/about/page-data.json\\" crossorigin=\\"use-credentials\\"/><style> .style3 </style><style> .style2 </style><style> .style1 </style><meta name=\\"generator\\" content=\\"Gatsby 2.0.0\\"/></head><body><noscript id=\\"gatsby-noscript\\">This app works best with JavaScript enabled.</noscript><div id=\\"___gatsby\\"><div style=\\"outline:none\\" tabindex=\\"-1\\" role=\\"group\\" id=\\"gatsby-focus-wrapper\\"></div></div><script id=\\"gatsby-script-loader\\">/*<![CDATA[*/window.pagePath=\\"/about/\\";window.webpackCompilationHash=\\"1234567890abcdef1234\\";/*]]>*/</script><script id=\\"gatsby-chunk-mapping\\">/*<![CDATA[*/window.___chunkMapping={};/*]]>*/</script></body></html>"`;

exports[`static-entry onPreRenderHTML can be used to replace postBodyComponents 1`] = `"<!DOCTYPE html><html><head><meta charSet=\\"utf-8\\"/><meta http-equiv=\\"x-ua-compatible\\" content=\\"ie=edge\\"/><meta name=\\"viewport\\" content=\\"width=device-width, initial-scale=1, shrink-to-fit=no\\"/><meta name=\\"generator\\" content=\\"Gatsby 2.0.0\\"/><link as=\\"fetch\\" rel=\\"preload\\" href=\\"/page-data/about/page-data.json\\" crossorigin=\\"use-credentials\\"/></head><body><noscript id=\\"gatsby-noscript\\">This app works best with JavaScript enabled.</noscript><div id=\\"___gatsby\\"><div style=\\"outline:none\\" tabindex=\\"-1\\" role=\\"group\\"></div></div><script id=\\"gatsby-chunk-mapping\\">/*<![CDATA[*/window.___chunkMapping={};/*]]>*/</script><script id=\\"gatsby-script-loader\\">/*<![CDATA[*/window.pagePath=\\"/about/\\";window.webpackCompilationHash=\\"1234567890abcdef1234\\";/*]]>*/</script><div> div3 </div><div> div2 </div><div> div1 </div></body></html>"`;
exports[`static-entry onPreRenderHTML can be used to replace postBodyComponents 1`] = `"<!DOCTYPE html><html><head><meta charSet=\\"utf-8\\"/><meta http-equiv=\\"x-ua-compatible\\" content=\\"ie=edge\\"/><meta name=\\"viewport\\" content=\\"width=device-width, initial-scale=1, shrink-to-fit=no\\"/><meta name=\\"generator\\" content=\\"Gatsby 2.0.0\\"/><link as=\\"fetch\\" rel=\\"preload\\" href=\\"/page-data/about/page-data.json\\" crossorigin=\\"use-credentials\\"/></head><body><noscript id=\\"gatsby-noscript\\">This app works best with JavaScript enabled.</noscript><div id=\\"___gatsby\\"><div style=\\"outline:none\\" tabindex=\\"-1\\" role=\\"group\\" id=\\"gatsby-focus-wrapper\\"></div></div><script id=\\"gatsby-chunk-mapping\\">/*<![CDATA[*/window.___chunkMapping={};/*]]>*/</script><script id=\\"gatsby-script-loader\\">/*<![CDATA[*/window.pagePath=\\"/about/\\";window.webpackCompilationHash=\\"1234567890abcdef1234\\";/*]]>*/</script><div> div3 </div><div> div2 </div><div> div1 </div></body></html>"`;

exports[`static-entry onPreRenderHTML can be used to replace preBodyComponents 1`] = `"<!DOCTYPE html><html><head><meta charSet=\\"utf-8\\"/><meta http-equiv=\\"x-ua-compatible\\" content=\\"ie=edge\\"/><meta name=\\"viewport\\" content=\\"width=device-width, initial-scale=1, shrink-to-fit=no\\"/><meta name=\\"generator\\" content=\\"Gatsby 2.0.0\\"/><link as=\\"fetch\\" rel=\\"preload\\" href=\\"/page-data/about/page-data.json\\" crossorigin=\\"use-credentials\\"/></head><body><div> div3 </div><div> div2 </div><div> div1 </div><noscript id=\\"gatsby-noscript\\">This app works best with JavaScript enabled.</noscript><div id=\\"___gatsby\\"><div style=\\"outline:none\\" tabindex=\\"-1\\" role=\\"group\\"></div></div><script id=\\"gatsby-script-loader\\">/*<![CDATA[*/window.pagePath=\\"/about/\\";window.webpackCompilationHash=\\"1234567890abcdef1234\\";/*]]>*/</script><script id=\\"gatsby-chunk-mapping\\">/*<![CDATA[*/window.___chunkMapping={};/*]]>*/</script></body></html>"`;
exports[`static-entry onPreRenderHTML can be used to replace preBodyComponents 1`] = `"<!DOCTYPE html><html><head><meta charSet=\\"utf-8\\"/><meta http-equiv=\\"x-ua-compatible\\" content=\\"ie=edge\\"/><meta name=\\"viewport\\" content=\\"width=device-width, initial-scale=1, shrink-to-fit=no\\"/><meta name=\\"generator\\" content=\\"Gatsby 2.0.0\\"/><link as=\\"fetch\\" rel=\\"preload\\" href=\\"/page-data/about/page-data.json\\" crossorigin=\\"use-credentials\\"/></head><body><div> div3 </div><div> div2 </div><div> div1 </div><noscript id=\\"gatsby-noscript\\">This app works best with JavaScript enabled.</noscript><div id=\\"___gatsby\\"><div style=\\"outline:none\\" tabindex=\\"-1\\" role=\\"group\\" id=\\"gatsby-focus-wrapper\\"></div></div><script id=\\"gatsby-script-loader\\">/*<![CDATA[*/window.pagePath=\\"/about/\\";window.webpackCompilationHash=\\"1234567890abcdef1234\\";/*]]>*/</script><script id=\\"gatsby-chunk-mapping\\">/*<![CDATA[*/window.___chunkMapping={};/*]]>*/</script></body></html>"`;
13 changes: 11 additions & 2 deletions packages/gatsby/cache-dir/ensure-resources.js
Original file line number Diff line number Diff line change
Expand Up @@ -169,8 +169,17 @@ class EnsureResources extends React.Component {
if (!this.hasResources(this.state.pageResources) && isInitialRender) {
window.___failedResources = true

// prevent hydrating
throw new Error(`Missing resources for ${this.state.location.pathname}`)
console.error(`Missing resources for ${this.state.location.pathname}`)
// Code below cause partial hydration. Anything above will be properly hydrated,
// but there's really not much other than LocationHandler and any wrappers
// added by wrapRootElement. <div> will mount in place of @reach/router's wrapper
// and preserve DOM elements from static html.
return (
<div
dangerouslySetInnerHTML={{ __html: `` }}
suppressHydrationWarning
/>
)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@davidbailey00 I would like sanity check here:
this seems to do similar thing (preventing react from cleaning up ___gatsby div) and it works in more scenarios than throwing (in case we throw before any parent component "renders" any DOM element, react will wipe ___gatsby div). It seems like we were "lucky" with this, because

was always there coming from above . My change moves below so no DOM element is above, which was causing issues.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this means we will do a full client rehydration if something goes wrong, right? maybe add a comment about it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's partial hydration - things above the actual page will be hydrated - so if users use wrapRootElement/wrapPageElement or gatsby-plugin-layout those will be actually hydrated, but the content of the page itself (in case template chunk or query results can't be loaded) won't be trully hydrated, but content from static html will be there

This is a neat trick that you can do when using:

<div
          dangerouslySetInnerHTML={{ __html: `` }}
          suppressHydrationWarning
        />

during hydration, as it won't try to actually change DOM nodes under it.

But yeah, I should add more context there for sure

}

isInitialRender = false
Expand Down
1 change: 1 addition & 0 deletions packages/gatsby/cache-dir/loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,7 @@ const queue = {
const page = {
componentChunkName: pageData.componentChunkName,
path: pageData.path,
matchPath: pageData.matchPath,
webpackCompilationHash: pageData.webpackCompilationHash,
}

Expand Down
2 changes: 1 addition & 1 deletion packages/gatsby/cache-dir/page-renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class PageRenderer extends React.Component {
replacementElement ||
createElement(this.props.pageResources.component, {
...props,
key: this.props.pageResources.page.path,
key: this.props.path || this.props.pageResources.page.path,
})

const wrappedPage = apiRunner(
Expand Down
Loading