gatsby: Hot reloading CSS broken when component lives in wrapPageElement

Description

I’m using Styled Components (and the gatsby plugin for it) but I can confirm this is an issue with CSS modules as well.

Hot reloading of CSS works great when you are editing a component on a page.

However if you use the wrapPageElement or wrapRootElement API in gatsby-browser.js and have a styled component that lives in that layout, it’s reloads the whole page - losing at state you might have.

export function wrapPageElement({ element, props }) {
  return <Layout {...props}>{element}</Layout>;
}

So for example, if I have a Layout component:

export default function Layout({ children }) {
  return (
    <>
      <div>
          <Nav></Nav>
          {children}
      </div>
    </>
  );
}

And then either in Layout.js directry, or inside of another component - like Nav - I have my styled component:

const NavStyles = styled.nav`
  background: green;
`;

Now if I change green to blue. The whole page reloads.

If I were to move that Nav component out of Layout.js and into a page like pages/index.js, it hot reloads fine without reloading the page.

Environment

This happens in both Firefox and Chrome

System: OS: macOS 10.15.2 CPU: (16) x64 Intel® Core™ i9-9880H CPU @ 2.30GHz Shell: 3.2.57 - /bin/bash Binaries: Node: 13.9.0 - /usr/local/bin/node Yarn: 1.22.0 - /usr/local/bin/yarn npm: 6.13.7 - /usr/local/bin/npm Languages: Python: 2.7.15 - /usr/local/bin/python Browsers: Chrome: 81.0.4044.122 Firefox: 59.0.1 Safari: 13.0.4 npmGlobalPackages: gatsby: 2.15.14

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 3
  • Comments: 24 (15 by maintainers)

Most upvoted comments

Is there a plan to switch to Fast Refresh by default? React Hot Loader is extremely fragile and I hope we can phase it out asap.

@gaearon I’m absolutely tracking all of this 😃 Here’s our rough plan of action:

  • take part in stabilizing the refresh plugin ecosystem and keep it incorporated with gatsby
  • Gatsby V3 will raise the bar for minimum react version, which allows us to make fast-refresh the default dev experience
  • continue to support hot-loader until preact is compatible with fast-refresh

Since fast-refresh should fix these rough edges for us, I don’t think it’s worth our effort fixing this in hot-loader as it will eventually be fully replaced.

Ah, you sorted it out, good stuff. The ol’ plug it-out-and-plug-it-back-in-again trick! 😃

Do you know if I can stick GATSBY_HOT_LOADER=fast-refresh in an .env file? I’ve tried .env and .env.development, but both are ignored. Not sure how well sticking it in package.json will work for windows users

Unfortunately this will likely not work right now. We are aware of this and do plan improvement and streamlining those for next major - https://github.com/gatsbyjs/gatsby/issues/21004 but those will need breaking changes so those are reserver for v3.

Is there a plan to switch to Fast Refresh by default? React Hot Loader is extremely fragile and I hope we can phase it out asap.

Yes! We just can’t do it in version 2 of Gatsby, because it still supports react/react-dom@>=16.4.2 and while we were researching Fast Refresh we found in some of comments that it needs at least 16.10 (or so, I don’t remember right now). This is planned for next major as well. I personally am also bit weary of disclaimer that currently there is in README for react-refresh:

This is an experimental package for hot reloading.

Its API is not as stable as that of React, React Native, or React DOM, and does not follow the common versioning scheme.

Use it at your own risk.

So we do hope that timing will align and react-refresh will be marked as stable before/during our v3 work.