Emotion: Big performance hit when using Emotion with React

Created on 28 Jun 2020  路  4Comments  路  Source: emotion-js/emotion

The Problem
I have a peculiar issue and I am not sure if its react's, emotionjs' or my fault - When using EmotionJs in my React app everything slows down to a crawl, but when running the same code on CodeSandBox it runs fast. The only differences are that the CodeSandBox example is not nested in a navigator and that I am using the

/** @jsx jsx */
import { jsx, css } from "@emotion/core";

syntax in the example instead of just import { css } from "@emotion/core".

Current behavior:

Performance gif

To reproduce:

CodeSandbox Example

Expected behavior:


I expected CodeSandBox and my React app to behave the same way.

Environment information:

  • react versions:
    "@babel/preset-react": "^7.9.4",
    "@hot-loader/react-dom": "^16.13.0",
    "@types/react": "^16.9.34",
    "eslint-plugin-react": "^7.19.0",
    "eslint-plugin-react-hooks": "^3.0.0",
    "react-hot-loader": "^4.12.20",
    "react": "^16.13.1",
    "react-dom": "^16.13.1",
    "react-router-dom": "^5.1.2"

  • emotion versions:
    "@emotion/babel-preset-css-prop": "^10.0.27",
    "@emotion/core": "^10.0.28",
    "babel-plugin-emotion": "^10.0.33",
    "eslint-plugin-emotion": "^10.0.27",

bug needs triage

Most helpful comment

I would expect this to be caused by the fact that you generate new styles very often (you have a 16ms interval and new styles are generated based on the mouse position). For very fast-changing styles (like during non-css animation) Emotion is not the best choice and style prop is better suited for that. It's because we rely heavily on caching and old rules are not removed from the document. However, it's not really that Emotion is the only culprit here - React itself is just not the best at handling very fast updates (like animations, or your 16ms interval). Most libraries doing animations in React (framer-motion, react-sprint) and in React Native (reanimated) are actually bypassing React to update styles to achieve much better performance - they manipulate things like style directly, using, for example, DOM APIs.

All 4 comments

I think it's hard to say without seeing your app code as well.
Can you try reproduce this in a new CodeSandbox where the conditions are similar to the app you're describing?

Thanks

The code is now as identical as possible in the sandbox, but I was not able to "eject" in codesandbox ( I couldn't find a way ) and configure tools like babel and webpack to make it 100% identical, so I've made a repo with the problem repo.

After more investigation it seems like the combination of Emotion and DarkReader causes the poor performance

I would expect this to be caused by the fact that you generate new styles very often (you have a 16ms interval and new styles are generated based on the mouse position). For very fast-changing styles (like during non-css animation) Emotion is not the best choice and style prop is better suited for that. It's because we rely heavily on caching and old rules are not removed from the document. However, it's not really that Emotion is the only culprit here - React itself is just not the best at handling very fast updates (like animations, or your 16ms interval). Most libraries doing animations in React (framer-motion, react-sprint) and in React Native (reanimated) are actually bypassing React to update styles to achieve much better performance - they manipulate things like style directly, using, for example, DOM APIs.

Closing this issue as I've answered a month ago and OP (or anyone else) has not responded back with any questions or a followup. Feel free to open a new issue if needed.

Was this page helpful?
0 / 5 - 0 ratings