React.NET: EmotionFunctions are broken with emotion 10+

Please verify these steps before filing an issue, and check them off as you go

  • The relevant native JavascriptEngineSwitcher library packages are installed (such as JavaScriptEngineSwitcher.V8.Native.win-x64)
  • The VC++ 2017 runtime is installed
  • The value of SetUseReact and SetUseBabel is correct in ReactConfig.cs or Startup.cs
  • I’ve looked at the sample projects in this repo to verify that my app is configured correctly

I’m using these library versions:

  • ReactJS.NET: 5.1.1
  • JavaScriptEngineSwitcher: 3.1.8
  • react and react-dom: 16.12.0
  • webpack: 4.41.2
  • node: 12.11.0

Runtime environment:

  • OS: Windows x64
  • .NET Framework or .NET Core Version: ASP.NET Core 3.1 preview 3

Steps to reproduce

Take the sample code from React.Sample.Webpack.CoreMvc and upgrade the project to ASP.NET Core 3.1 preview 3 (I assume that the behaviour is the same with 3.0, but I havn’t tried).

Remove the react-emotion package (v10 throw an error explaining that it’s deprecated and should be replaced with @emotion/core and @emotion/styled

At the end, I have the following package.json :

{
  "name": "my-app",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "scripts": {
    "build": "webpack"
  },
  "devDependencies": {
    "@babel/core": "^7.7.2",
    "@babel/plugin-proposal-class-properties": "^7.7.0",
    "@babel/plugin-syntax-dynamic-import": "^7.2.0",
    "@babel/preset-env": "^7.7.1",
    "@babel/preset-react": "^7.7.0",
    "@babel/preset-typescript": "^7.7.2",
    "babel-loader": "^8.0.6",
    "babel-plugin-emotion": "^10.0.23",
    "babel-runtime": "^6.26.0",
    "react-select": "^3.0.4",
    "reactstrap": "^8.0.0",
    "webpack": "^4.41.2",
    "webpack-cli": "^3.3.10"
  },
  "dependencies": {
    "@emotion/core": "^10.0.22",
    "@emotion/styled": "^10.0.23",
    "emotion": "^10.0.23",
    "emotion-server": "^10.0.17",
    "react": "^16.12.0",
    "react-dom": "^16.12.0",
    "react-helmet": "^5.2.1",
    "react-jss": "^10.0.0",
    "react-router-dom": "^5.1.2",
    "styled-components": "^4.0.0"
  }
}

In Content/component/emotion.jsx, replace import styled from 'react-emotion with import styled from '@emotion/styled';


When launching the app, an error occurs :

React.Exceptions.ReactScriptLoadException: Error while loading "~/dist/components.js": ReferenceError: 'document' is not defined

 ---> JavaScriptEngineSwitcher.Core.JsRuntimeException: ReferenceError: 'document' is not defined



Engine name: ChakraCoreJsEngine

Engine version: 1.11.13

Category: Runtime error

Description: 'document' is not defined

Type: ReferenceError

Document name: eval code

Line number: 109

Column number: 5

Source fragment:     container = options.container || document.head; ---> JavaScriptEngineSwitcher.ChakraCore.JsRt.JsScriptException: Script threw an exception.

   at JavaScriptEngineSwitcher.ChakraCore.JsRt.JsErrorHelpers.ThrowIfError(JsErrorCode error)

   at JavaScriptEngineSwitcher.ChakraCore.JsRt.JsContext.RunScript(String script, JsSourceContext sourceContext, String sourceUrl, JsParseScriptAttributes& parseAttributes)

   at JavaScriptEngineSwitcher.ChakraCore.ChakraCoreJsEngine.<>c__DisplayClass26_0.<InnerExecute>b__0()

   at JavaScriptEngineSwitcher.ChakraCore.ChakraCoreJsEngine.<>c__DisplayClass26_0.<InnerExecute>b__0()

   at JavaScriptEngineSwitcher.ChakraCore.ScriptDispatcher.<>c__DisplayClass11_0.<Invoke>b__0()

   at JavaScriptEngineSwitcher.ChakraCore.ScriptDispatcher.StartThread()

--- End of stack trace from previous location where exception was thrown ---

   at JavaScriptEngineSwitcher.ChakraCore.ScriptDispatcher.InnnerInvoke(Func`1 del)

   at JavaScriptEngineSwitcher.ChakraCore.ScriptDispatcher.Invoke(Action action)

   at JavaScriptEngineSwitcher.ChakraCore.ChakraCoreJsEngine.InnerExecute(String code, String documentName)

   at JavaScriptEngineSwitcher.Core.JsEngineBase.Execute(String code, String documentName)

   at React.JavaScriptEngineFactory.LoadUserScripts(IJsEngine engine)



   --- End of inner exception stack trace ---

   at React.JavaScriptEngineFactory.EnsureValidState()

   at React.JavaScriptEngineFactory.GetEngine()

   at React.ReactEnvironment.<.ctor>b__16_1()

   at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode)

   at System.Lazy`1.ExecutionAndPublication(LazyHelper executionAndPublication, Boolean useDefaultConstructor)

   at System.Lazy`1.CreateValue()

   at System.Lazy`1.get_Value()

   at React.ReactEnvironment.get_Engine()

   at React.ReactEnvironment.EnsureUserScriptsLoaded()

   at React.ReactEnvironment.CreateComponent(IReactComponent component, Boolean clientOnly)

   at React.Router.ReactEnvironmentExtensions.CreateRouterComponent[T](IReactEnvironment env, String componentName, T props, String path, String containerId, Boolean clientOnly)

   at React.Router.HtmlHelperExtensions.ReactRouter[T](IHtmlHelper htmlHelper, String componentName, T props, String path, String htmlTag, String containerId, Boolean clientOnly, Boolean serverOnly, String containerClass, Action`2 contextHandler, IRenderFunctions renderFunctions)

   at AspNetCore.Views_Home_Index.ExecuteAsync() in D:\Projects\MBaumann.Portfolio\src\MBaumann.Portfolio.WebApp\Views\Home\Index.cshtml:line 15

   at Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderPageCoreAsync(IRazorPage page, ViewContext context)

   at Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderPageAsync(IRazorPage page, ViewContext context, Boolean invokeViewStarts)

   at Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderAsync(ViewContext context)

   at Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor.ExecuteAsync(ViewContext viewContext, String contentType, Nullable`1 statusCode)

   at Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor.ExecuteAsync(ViewContext viewContext, String contentType, Nullable`1 statusCode)

   at Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor.ExecuteAsync(ActionContext actionContext, IView view, ViewDataDictionary viewData, ITempDataDictionary tempData, String contentType, Nullable`1 statusCode)

   at Microsoft.AspNetCore.Mvc.ViewFeatures.ViewResultExecutor.ExecuteAsync(ActionContext context, ViewResult result)

   at Microsoft.AspNetCore.Mvc.ViewResult.ExecuteResultAsync(ActionContext context)

   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeResultAsync>g__Logged|21_0(ResourceInvoker invoker, IActionResult result)

   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResultFilterAsync>g__Awaited|29_0[TFilter,TFilterAsync](ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)

   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResultExecutedContextSealed context)

   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext[TFilter,TFilterAsync](State& next, Scope& scope, Object& state, Boolean& isCompleted)

   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeResultFilters()

--- End of stack trace from previous location where exception was thrown ---

   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|24_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)

   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)

   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)

   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync()

--- End of stack trace from previous location where exception was thrown ---

   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)

   at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)

   at React.AspNet.BabelFileMiddleware.Invoke(HttpContext context)

   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

ReacjJS.NET doesn’t provide a container for server side rendering, so Emotion try to use the dom and crashed.

Note that Emotion seems to work fine (I don’t know it well, I’m certainly missing something) when removing EmotionFunctions from the ~/Views/Home/Index.cshtml view and removing import { renderStylesToString } from 'emotion-server'; and global.EmotionServer = { renderStylesToString }; from Content/component/expose-components.js.

If it helps, I can provide a sample on a new branch/PR, or will be happy to create a PR to fix it if it’s a good first issue.

About this issue

  • Original URL
  • State: open
  • Created 5 years ago
  • Comments: 17 (5 by maintainers)

Most upvoted comments

We where just going to start using ReactJS.NET and it worked great until we imported our component library which uses Emotion 10 (@emotion/core). The error we get is that any component that uses the css prop and the emotion jsx function will cause ReactJS.Net to throw an exception:

TypeError: Cannot read property 'key' of null

The reason being this line of code (from Emotion I think):

var insertStyles = function insertStyles(cache, serialized, isStringTag) {
var className = cache.key + "-" + serialized.name;

It seems that the cache object in their implementation is null. I’m not sure what is causing this, shouldn’t Emotion 10 be able to work without custom render functions and so on?

According to their documentation here: https://emotion.sh/docs/ssr using the default renderToString function:

import { renderToString } from 'react-dom/server'

should “just work”. As far as I can tell Emotion should no longer need access to the head etc since it inserts <style> tags instead.

Is there anyway I can help with more information @dustinsoftware ?

Try using JSEngineSwitcher.Node. It was released a few weeks ago and uses a real node engine.

On Thu, Mar 19, 2020 at 09:54, Johan Otterud notifications@github.com wrote:

A lot has changed in Emotion 10, but I think I am closer to a solution.

I got exactly the same error in node as in ReactJS.NET. It seems that the way I had set up my webpack it would build a bundle meant for a browser. That means Emotion will try to load things like document which is not available SSR.

So if I build my bundle in webpack using target: node it works in node, but then ReactJS.NET can’t handle it because it doesn’t like the require syntax…

So if I can build a bundle meant for the server that ReactJS.NET can consume it should work… 😛 Any ideas?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/reactjs/React.NET/issues/970#issuecomment-601295694, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAHGCFVTRA6DRVX5NFINVG3RIJE23ANCNFSM4JOLICDQ .

(Hi @RobertBolender 👋)

If you find any docs on updating to emotion 10 relevant to SSR, link them here…