diff --git a/e2e-tests/development-runtime/cypress/integration/navigation/linking.js b/e2e-tests/development-runtime/cypress/integration/navigation/linking.js index 587f015b99cfd..8225ecf39104e 100644 --- a/e2e-tests/development-runtime/cypress/integration/navigation/linking.js +++ b/e2e-tests/development-runtime/cypress/integration/navigation/linking.js @@ -150,16 +150,31 @@ describe(`navigation`, () => { }) it(`should trigger an effect after a search param has changed`, () => { - cy.findByTestId(`effect-message`).should(`have.text`, `Waiting for effect`) + cy.findByTestId(`effect-message`).should( + `have.text`, + `Waiting for effect` + ) cy.findByTestId(`send-search-message`).click().waitForRouteChange() - cy.findByTestId(`effect-message`).should(`have.text`, `?message=searchParam`) + cy.findByTestId(`effect-message`).should( + `have.text`, + `?message=searchParam` + ) }) it(`should trigger an effect after the hash has changed`, () => { - cy.findByTestId(`effect-message`).should(`have.text`, `Waiting for effect`) + cy.findByTestId(`effect-message`).should( + `have.text`, + `Waiting for effect` + ) cy.findByTestId(`send-hash-message`).click().waitForRouteChange() cy.findByTestId(`effect-message`).should(`have.text`, `#message-hash`) }) + + it(`should trigger an effect after the state has changed`, () => { + cy.findByTestId(`effect-message`).should(`have.text`, ``) + cy.findByTestId(`send-state-message`).click().waitForRouteChange() + cy.findByTestId(`effect-message`).should(`have.text`, `this is a message using the state`) + }) }) } @@ -173,7 +188,10 @@ describe(`navigation`, () => { it(`should trigger an effect after a search param has changed`, () => { cy.findByTestId(`effect-message`).should(`have.text`, ``) cy.findByTestId(`send-search-message`).click().waitForRouteChange() - cy.findByTestId(`effect-message`).should(`have.text`, `?message=searchParam`) + cy.findByTestId(`effect-message`).should( + `have.text`, + `?message=searchParam` + ) }) it(`should trigger an effect after the hash has changed`, () => { @@ -181,6 +199,12 @@ describe(`navigation`, () => { cy.findByTestId(`send-hash-message`).click().waitForRouteChange() cy.findByTestId(`effect-message`).should(`have.text`, `#message-hash`) }) + + it(`should trigger an effect after the state has changed`, () => { + cy.findByTestId(`effect-message`).should(`have.text`, ``) + cy.findByTestId(`send-state-message`).click().waitForRouteChange() + cy.findByTestId(`effect-message`).should(`have.text`, `this is a message using the state`) + }) }) } diff --git a/e2e-tests/development-runtime/src/pages/navigation-effects.js b/e2e-tests/development-runtime/src/pages/navigation-effects.js index f3c041d5c90ea..e9ad800964198 100644 --- a/e2e-tests/development-runtime/src/pages/navigation-effects.js +++ b/e2e-tests/development-runtime/src/pages/navigation-effects.js @@ -8,6 +8,7 @@ export default function NavigationEffects({ location }) { const searchParam = location.search const searchHash = location.hash + const searchState = location?.state?.message useEffect(() => { setMessage(searchParam) @@ -17,7 +18,12 @@ export default function NavigationEffects({ location }) { setMessage(searchHash) }, [searchHash]) - const handleClick = next => navigate(`${next}`, { replace: true }) + useEffect(() => { + setMessage(searchState) + }, [searchState]) + + const handleClick = (next, options = { replace: true }) => + navigate(`${next}`, options) return ( @@ -35,6 +41,17 @@ export default function NavigationEffects({ location }) { > Send Hash + + ) } diff --git a/packages/gatsby/cache-dir/navigation.js b/packages/gatsby/cache-dir/navigation.js index a117bff6d7fc4..095ed635d2311 100644 --- a/packages/gatsby/cache-dir/navigation.js +++ b/packages/gatsby/cache-dir/navigation.js @@ -198,6 +198,18 @@ class RouteAnnouncer extends React.Component { } } +const compareLocationProps = (prevLocation, nextLocation) => { + if (prevLocation.href !== nextLocation.href) { + return true + } + + if (prevLocation?.state?.key !== nextLocation?.state?.key) { + return true + } + + return false +} + // Fire on(Pre)RouteUpdate APIs class RouteUpdates extends React.Component { constructor(props) { @@ -210,16 +222,15 @@ class RouteUpdates extends React.Component { } shouldComponentUpdate(prevProps) { - if (this.props.location.href !== prevProps.location.href) { + if (compareLocationProps(prevProps.location, this.props.location)) { onPreRouteUpdate(this.props.location, prevProps.location) return true } - return false } componentDidUpdate(prevProps) { - if (this.props.location.href !== prevProps.location.href) { + if (compareLocationProps(prevProps.location, this.props.location)) { onRouteUpdate(this.props.location, prevProps.location) } }