emotion: TypeError: Cannot read property 'key' of null on SSR

Current behavior:

Using the css property works on the client, but on SSR gives this error:

Encountered error "#<ExecJS::ProgramError: TypeError: Cannot read property 'key' of null>" when prerendering HelloWorld with {"greeting":"Hello from react-rails."}
insertStyles ((execjs):2165:25)

Related issue: https://github.com/emotion-js/emotion/issues/1185

To reproduce:

The app I’m integrating this in is a Rails app using https://github.com/reactjs/react-rails so I made a repro with it. Hopefully you have ruby installed 🤞.

git clone git@github.com:ksweetie/emotion-ssr.git
cd emotion-ssr/
bundle
yarn
rails s
// visit localhost:3000/foo/foo

Here’s a list of files I changed, otherwise it’s a stock Rails app. Changing prerender: true to false in foo.html.erb should show that it’s working on the client.

app/views/foo/foo.html.erb
app/javascript/components/HelloWorld.tsx
config/webpack/loaders/typescript.js
tsconfig.json
babel.config.js

Expected behavior:

Turning on SSR doesn’t give an error.

Environment information:

  • react version: 16.12.0
  • emotion version: 10.0.27

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 1
  • Comments: 18 (6 by maintainers)

Most upvoted comments

I was using emotion v10.0.9, and it was working fine. Once I went to v10.0.27, that’s when the issue occurred.

The issue is that cache is null in render inside of @emotion/core. So when it calls utils.getRegisteredStyles and utils.insertStyles, it breaks.

The codebase I’m working with is using Enzyme. If I mount, it breaks the test in the same way as the original poster. All css props activate without a cache provider, and it’s not creating one.

I believe it’s because of this:

var EmotionCacheContext = React.createContext( // we're doing this to avoid preconstruct's dead code elimination in this one case
// because this module is primarily intended for the browser and node
// but it's also required in react native and similar environments sometimes
// and we could have a special build just for that
// but this is much easier and the native packages
// might use a different theme context in the future anyway
typeof HTMLElement !== 'undefined' ? createCache() : null);

Specifically typeof HTMLElement !== 'undefined'. It’s not auto-creating a cache when that happens.

@lucat1 this particular problem happens because .10 and .12 prereleases got mixed there and there were some breaking changes in between them, so older version of @emotion/css has been crashing while using newer @emotion/cache. I’ve prepared a PR to fix this: https://github.com/zeit/next.js/pull/11414

@srmagura I don’t think it’s a bug. I was defining document globally on server side and I shouldn’t do that.

This solved our problems also, we needed to do some SSR using ReactJS.NET (run React components in ASP.NET) and had to build using webpack with target: “web” (the default). The monkey patch works but what also worked for me that doesn’t require the monkey patch was setting this in webpack:

resolve: {
    aliasFields: ["module"] // Setting to "main" also works
  },

This tells webpack to use the module or main field instead of the browser field. Could perhaps have effects on other packages though but worked for me… There is also a setting called mainFields in webpack but I am not sure what the difference is between mainField and aliasField, and setting the mainField did not work.

Would be interesting to hear if setting the aliasField works for you also?

@KevinGhadyani-minted would you be willing to join our Slack and debug this with me?