- Published on
Set Up Storybook Decorators - Emotion Theme Provider
- Authors

- Name
- Duncan Leung
- @leungd
Related Post: Set Up Storybook Decorators - React Intl Provider
Problem: Storybook Not Recognizing Emotion Theme Provider
I was running into an issue setting up Storybook with Emotion Theming.
I was receiving an error when attempting to create a Storybook decorator with Emotion's <ThemeProvider />:
Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
Check the render method of `storyFn`.
I had set up Emotion's Theme provider in Storybook .storybook/preview.js in the similar pattern that React context providers are set up - Using a provider to pass the current theme to the tree below.
import { ThemeProvider } from "emotion-theming";
import theme from "~/theme";
addDecorator((story) => (
<>
<GlobalStyles />
<ThemeProvider theme={theme}>
<div style={{ padding: "3rem" }}>{story()}</div>
</ThemeProvider>
</>
));
This was the pattern used in our parent <App /> React component.
import { ThemeProvider } from "emotion-theming";
import theme from "~/theme";
import { ModalProvider } from "~/components/Modal";
/**
* This component provides a reusable application wrapper for use
* in Gatsby APIs, testing, etc.
*/
const App = ({ element }: { element: ReactNode }) => {
return (
<ThemeProvider theme={theme}>
<ModalProvider>{element}</ModalProvider>
</ThemeProvider>
);
};
export default App;
Extract ThemeProvider into its own Decorator
The fix is to extract Emotion's <ThemeProvider /> into its own decorator.
import { addDecorator } from "@storybook/react";
import { EmotionThemeProvider } from "./decorators";
import GlobalStyles from "../src/components/Layout/GlobalStyles";
// Global Styles ==============================
addDecorator((story) => (
<>
<GlobalStyles />
<div style={{ padding: "3rem" }}>{story()}</div>
</>
));
// Emotion Theme Provider =====================
addDecorator(EmotionThemeProvider);
// ... other decorators
import { ThemeProvider } from "emotion-theming";
import theme from "~/theme";
const EmotionThemeProvider = (storyFn) => (
<ThemeProvider theme={theme}>{storyFn()}</ThemeProvider>
);
export default EmotionThemeProvider;
Gatsby Starter: TypeScript + Emotion + Storybook
If you want to see the full config in a project, I created a Gatsby Starter that uses Gatsby + TypeScript + Emotion + Storybook + React Intl + SVGR + Jest.
Check it out at: Gatsby Starter: TypeScript + Emotion + Storybook