Gatsby: Gatsby 2.0 RC | Styled components theme crashes prod build

Created on 3 Sep 2018  路  29Comments  路  Source: gatsbyjs/gatsby

Description

When using the <ThemeProvider>, everything works as expected in development. When building for production, an error occurs.

Steps to reproduce

Use a <ThemeProvider> and in a component, use theme values, such as ${props => props.theme.colors.green}. See that it works in development when running gatsby develop but crashes when running gatsby build.

Expected result

The prod build should complete successfully.

Actual result

error Building static HTML for pages failed

   3 |
   4 | const StyledFontAwesomeIcon = styled(FontAwesomeIcon)`
 > 5 |   color: ${props => props.theme.colors.green};
     |                                        ^
   6 |   margin-right: 15px;
   7 | `
   8 |

WebpackError: TypeError: Cannot read property 'green' of undefined

Environment

System:
OS: macOS High Sierra 10.13.6
CPU: x64 Intel(R) Core(TM) i7-4870HQ CPU @ 2.50GHz
Shell: 5.3 - /bin/zsh
Binaries:
Node: 10.4.0 - /usr/local/bin/node
Yarn: 1.7.0 - /usr/local/bin/yarn
npm: 6.1.0 - /usr/local/bin/npm
Browsers:
Chrome: 68.0.3440.106
Firefox: 61.0.1
Safari: 11.1.2
npmPackages:
gatsby: ^2.0.0-rc.7 => 2.0.0-rc.7
gatsby-plugin-react-helmet: ^3.0.0-rc.1 => 3.0.0-rc.1
gatsby-plugin-styled-components: ^3.0.0-rc.1 => 3.0.0-rc.1
npmGlobalPackages:
gatsby-cli: 2.0.0-rc.1

question or discussion

Most helpful comment

You also have to use the wrapPage thingy in gatsby-ssr.js

All 29 comments

Hi @thibautvs, would it be possible for you to provide a demo project? This makes your issue much easier to diagnose.

Hi @kakadiadarpan,

Sure! Pretty busy these days but I'll try to find some time to put a sample project together.

Just upgraded to gatsby 2.0.1 and gatsby-plugin-styled-components 3.0.0. Still the same issue...

@thibautvs I just created a repo demonstrating the usage of styled-components, the gatsby plugin, and ThemeProvider and was unable to reproduce.

Here's the demo in Netlify showing the built site

I'm going to close this one out until you can reproduce! Thanks for your patience!

Hello @DSchau,

I could reproduce the problem in this repo: https://github.com/thibautvs/gatsby-theme-crash

Kind regards,

Thibaut

Hello @kakadiadarpan,

I provided a demo project (https://github.com/thibautvs/gatsby-theme-crash).

Kind regards,

Thibaut

@thibautvs Have you found a solution for this yet? I am having the same problem when I migrated to Gatsby 2.0

@EricSSartorius Nope haven't found the problem, though I could isolate it like in the provided repo. It essentially works almost all the time, except for a particular page. Maybe it's related to some 3rd party dependencies, might be worth commenting them out one by one to (in)validate this hypothesis.

@LeKoArts Maybe we can now remove the label "status: needs reproduction"?
@kakadiadarpan Maybe we can now remove the label "status: needs more info"?

Thx!

your styled components dependency is outdated

@thibautvs I was wondering if you ever figured out what was causing this? I'm having the same issue intermittently.

@Vpr99 I'm still experiencing the same issue

@thibautvs bummer. I managed to make it work by wrapping just that component in its own ThemeProvider but that feels super bad.

I ran into this another 5 or 6 times today. Any chance we could reopen @DSchau ? It looks like @thibautvs got a reproducible demo.

@thibautvs the main issue that's happening in your example is that src/pages/index/StyledFontAwesomeIcon.js is being treated as a page component, and is _not_ being wrapped with the special Layout component. This is leading the component to be rendered during SSR without a ThemeProvider, thus, the error that theme is not defined.

I'd recommend that if you have React components that are just that (components!) instead of pages, that you create a src/components directory, and place components in that directory. Then those components can be imported into page components like one would expect.

Here's the fix for the reproduction -> https://github.com/thibautvs/gatsby-theme-crash/pull/1

@Vpr99 I can't fix your problem without a reproduction, unless it's a similar one to the one in this case. We've shown that it works with a recommended setup here so unless you can provide a separate reproduction of your issue, can't help much yet! Please do let us know if we can help further.

@DSchau thanks for the detailed response鈥擨 guess I didn't look close enough at Thibaut's repo. My problem is slightly different since I'm using wrapRootElement to wrap the entire site in the ThemeProvider. It seems to be super intermittent, but I'll try and make a repro here in a few.

Thanks again!

Thanks very much for your explanation and fix @DSchau!

Okay @DSchau I've managed to get a working reproduction of my issue:

https://github.com/Vpr99/gatsby-sc-reproduction

Please take a look when you have a sec鈥擨'm really stumped.

You also have to use the wrapPage thingy in gatsby-ssr.js

@LekoArts you're a legend. Thank you SO much :clap:

@Vpr99 you could also just use a Layout component there as well, correct? Seems weird to have a base template that you use to wrap, when that effectively _is_ a Layout component.

Good q. There were a couple reasons I ended up moving to wrapRootElement. First was analytics. I'm using react-tracking and I want to fire tracking events when each page mounts. Eg:

import track from 'react-tracking';

const Home = () => (
  <main>Home<main>
);

export default track({ page: 'home' })(Home);

If I'd imported BaseLayout in each page, I would have had to pass that analytics information as props to BaseLayout, since that's where the events are gathered and dispatched:

const Home = () => (
  <BaseLayout analyticsPage="home">Home<BaseLayout>
);

export default Home;
const BaseLayout = ({ children }) => (
  <main>{children}<main>
);

export default track(props => ({ page: props.analyticsPage }))(BaseLayout);

I liked being able to get rid of an extra prop, but both work just fine. In fact, before I discovered wrapRootElement, that's what I was doing.

Second, there were a couple situations where I wanted to apply some layout (e.g. CSS Grid) to the BaseLayout, to avoid adding extra divs. Most of the time this was fine, but there were a couple times where I wanted to access theme variables, but I couldn't since I was outside the scope of the ThemeProvider.

Anyways that was my thought process. There are probably better ways to tackle those problems, but that's how I got to where I'm at :) Thanks again for all your help @DSchau.

@DSchau I am new to gatsby and I've looked at your example: https://github.com/DSchau/gatsby-7827
I just wonder why can't we use the gatsby-browser API and its wrapRootElement to wrap all the app with ThemeProvider 馃. In your example the ThemeProvider will unmount and remount at each page change. I thought wrapRootElement was meant to be used with providers.
That's what I am doing here https://github.com/sylvhama/shamann-gatsby but the build fails.

Ok I omited to setup gatsby-ssr.js which should contain wrapRootElement as well. The Behind the scenes doc explains why we must do that: https://www.gatsbyjs.org/docs/webpack-and-ssr/

This addition to gatsby-ssr.js should really be documented in the gatsby-plugin-styled-components README as it essentially means that the plugin is broken out of the box (gatsby build fails if using themes).

The plugin isn鈥檛 broken nor not working with themes. There鈥檚 something wrong on your end. Can you share a reproduction repo?

Sorry, didn't mean to imply that the plugin itself is broken. It does require an extra step of configuration in order to work that I did not see documented in the plugin. Specifically, the code that needs to be added to gatsby-ssr.js that @sylvhama linked to. I think including example code for gatsby-ssr.js in the README would be very helpful.

I solved mine by also exporting the wrapRootElement in gatsby-ssr.js. It is suggested by gatsby documentation to use both.

You also have to use the wrapPage thingy in gatsby-ssr.js

Fixed it for me!

Was this page helpful?
0 / 5 - 0 ratings