Gatsby: Styled-components and common layout breaks the build

Created on 31 Jan 2019  路  8Comments  路  Source: gatsbyjs/gatsby

Description

Hi there, I'm new to gatsby and find it pretty awesome but I stumble across this problem which I created a repo to reproduce

If I use a custom Layout to be used throughout my app, and use it in ./gatsby-browser.js like so

const React = require('react');
const Layout = require('./src/Layout').default;

const LayoutRenderer = ({ PageComponent, pageProps }) => {
  return (
    <Layout>
      <PageComponent {...pageProps} />
    </Layout>
  );
};

export const replaceComponentRenderer = ({ props: { pageResources, ...pageProps } }) => (
  <LayoutRenderer PageComponent={pageResources.component} pageProps={pageProps} />
);

and with this in ./src/Layout.jsx including a theme for styled-components

import * as React from 'react';
import styled from 'styled-components';

const Bordered = styled('div')`
  border: 1px solid red;
`;

const mainTheme = {
  colors: {
    mainDark: "red",
  }
}

export default ({ children }) => (
  <ThemeProvider theme={mainTheme}>
    <Bordered>
      {children}
    </Bordered>
  </ThemeProvider>
);

With this in my src/pages/index.js

import React from "react"
import styled, {聽css } from "styled-components"

const Div = styled.div`
  ${({theme}) => css`
    color: ${theme.colors.mainDark};
  `}
`

export default () => <Div>Hello world!</Div>

I get a WebpackError: TypeError: Cannot read property 'mainDark' of undefined on gatsby build

and no error when I gatsby develop

I'm pretty sure I misunderstood something but can't find what!
Thanks for your help

Steps to reproduce

git clone https://github.com/martinratinaud/gatsby-layout-styled-components-problem.git
cd gatsby-layout-styled-components-problem
yarn
gatsby build

Expected result

Build should work

Actual result

Build fails with WebpackError: TypeError: Cannot read property 'mainDark' of undefined

Environment

System:
OS: macOS 10.14.2
CPU: (8) x64 Intel(R) Core(TM) i7-4870HQ CPU @ 2.50GHz
Shell: 3.2.57 - /bin/bash
Binaries:
Node: 11.7.0 - ~/.nvm/versions/node/v11.7.0/bin/node
Yarn: 1.13.0 - ~/.nvm/versions/node/v11.7.0/bin/yarn
npm: 6.6.0 - ~/.nvm/versions/node/v11.7.0/bin/npm
Languages:
Python: 2.7.10 - /usr/bin/python
Browsers:
Chrome: 71.0.3578.98
Safari: 12.0.2
npmPackages:
gatsby: ^2.0.104 => 2.0.104
gatsby-plugin-styled-components: ^3.0.4 => 3.0.4
npmGlobalPackages:
gatsby-cli: 2.4.8

question or discussion

Most helpful comment

Hi there, so here is the solution thanks to @sidharthachatterjee.

You have to add a gatsby-ssr.js exporting wrapRootElement

import React from 'react';
import { ThemeProvider } from 'styled-components';

const mainTheme = {
  colors: {
    mainDark: "red",
  }
}
export const wrapRootElement = ({ element }) => (
  <ThemeProvider theme={mainTheme}>{element}</ThemeProvider>
);

Thanks a lot for your help

All 8 comments

Thanks for reporting this issue.We are looking into it meanwhile you can use below mentioned snippet


export default ({ children }) => (
  <ThemeProvider theme={mainTheme.colors}>
    <Bordered>
      {children}
    </Bordered>
  </ThemeProvider>
);

const Div = styled.div
${({theme}) => css color: ${theme.mainDark}; }

if this answers your query feel free to close this issue

@martinratinaud This is likely because during SSR on build, there's no Provider and hence no theme

I'd recommend using wrapRootElement for the Provider and put it in both gatsby-browser.js
and gatsby-ssr.js

That should fix this

@gagandeepp thanks but I'm pretty sure if the theme is empty, then it won't work either ?
Or maybe it's just because it is SSR and it will update later ?

@sidharthachatterjee ok but I'm sorry if I don't understand Gatsby well yet but even with the docs I didn't find a relevant snippet. Can you help ?

@martinratinaud you tagged the wrong gagandeep. Let me tag the correct one @gagandeepp

@gagandeepp and @gagandeep Sorry about that :-)

Hi there, so here is the solution thanks to @sidharthachatterjee.

You have to add a gatsby-ssr.js exporting wrapRootElement

import React from 'react';
import { ThemeProvider } from 'styled-components';

const mainTheme = {
  colors: {
    mainDark: "red",
  }
}
export const wrapRootElement = ({ element }) => (
  <ThemeProvider theme={mainTheme}>{element}</ThemeProvider>
);

Thanks a lot for your help

I'm using ThemeProvider and this does not work for me

Was this page helpful?
0 / 5 - 0 ratings

Related issues

3CordGuy picture 3CordGuy  路  3Comments

ferMartz picture ferMartz  路  3Comments

timbrandin picture timbrandin  路  3Comments

brandonmp picture brandonmp  路  3Comments

kalinchernev picture kalinchernev  路  3Comments