Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add dev hint about css object being stringified by accident #1219

Merged
merged 2 commits into from
Oct 22, 2019

Conversation

Andarist
Copy link
Member

@Andarist Andarist commented Feb 9, 2019

No description provided.

@netlify
Copy link

netlify bot commented Feb 9, 2019

Preview Docs

Built with commit 2c61e9d

https://deploy-preview-1219--emotion.netlify.com

Copy link
Member

@emmatown emmatown left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not a big fan of this, while it would help some people, I'm worried that toString will be called for random reasons(iirc react-hot-loader might have done this) and people will open issues with "why is there some random error, i'm not doing what it says i'm doing". This used to be problem with the component selector error, it used to throw on toString but toString was getting called for random reasons and it was expected that it didn't have side effects and didn't throw so the error was moved to serialization.

@Andarist
Copy link
Member Author

Andarist commented Feb 9, 2019

Hm, maybe it was called on components because they were components that react hot loader had tried to patch somehow? Not sure why regular object would get stringified by accident 🤔

@emmatown
Copy link
Member

I had an idea, what if we returned this message from toString so when people inspect the dom, they'll see the message but toString doesn't have any side effects that could cause confusion if somehow stringified for another reason?

@codecov
Copy link

codecov bot commented Feb 24, 2019

Codecov Report

Merging #1219 into master will increase coverage by 0.05%.
The diff coverage is 100%.

Impacted Files Coverage Δ
packages/serialize/src/index.js 100% <100%> (ø) ⬆️
packages/jest-emotion/src/utils.js 98.85% <0%> (+1.14%) ⬆️

@Andarist
Copy link
Member Author

Not sure if I follow - how people inspecting the DOM would see our message?

@emmatown
Copy link
Member

Something like this, https://codesandbox.io/s/73kjljkzv6

@Andarist
Copy link
Member Author

Ok, this is clever XD So you would basically like to move the error message from console.error to return?

@emmatown
Copy link
Member

Yes.

@changeset-bot
Copy link

changeset-bot bot commented Oct 11, 2019

🦋 Changeset is good to go

Latest commit: c20e955

We got this.

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@Andarist
Copy link
Member Author

@mitchellhamilton I've updated this long-forgotten PR. Should be ready to merge now.


test('`css` opaque object passed in as `className` prop', () => {
// react-test-renderer doesn't stringify `className` (unlike react-dom)
// we need to pass dummy `css` prop so `jsx` tries to handle it (and stringify the `className`)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we use react testing library so we're using react-dom here and encounter what will happen in the browser?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

used testing library

@Andarist
Copy link
Member Author

I've adjusted the PR according to your suggestion 👍

I must say though that I'm not entirely sold on that toString trick. Seems for me that often console.error is easier to spot and the stack is attached to it, so it's also easier to find quickly the exact faulty call site. Can't see when this would matter as css opaque object is not intended for anything else other than emotion and it shouldn't be consumed in any other way - so if this gets stringified for any other reason it's immediately breaking a contract and I think we shouldn't care about such possibility, this simply should not be allowed.

Copy link
Member

@emmatown emmatown left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!!

@Andarist
Copy link
Member Author

@mitchellhamilton what about my reservations about just using toString trick without console.error? Should we switch back to console.error or do you think this is fine as is?

@emmatown
Copy link
Member

I think it's fine as it is. Based on the "why is there [object Object] on my element" issues, I think it'll address the problem because the first thing people will probably do if a style isn't being applied is inspect the element where they'll see this text. Also, I want to avoid toString functions that log/have visible side effects in general because we've been burned by it in the past when the error about not using the babel plugin when using component selectors showed up when people weren't even interpolating it because it was in the toString(it's since been moved to serialize)

@Andarist Andarist merged commit 4fc5657 into master Oct 22, 2019
@Andarist Andarist deleted the dev-hint/stringified-css-obj branch October 22, 2019 10:16
@github-actions github-actions bot mentioned this pull request Oct 22, 2019
@mycarrysun
Copy link

It might be helpful to add some extra note in the error message that you can use css that is exported from core instead of adding it to the css prop on an element. I had to do it this way to use React.cloneElement - I was able to accomplish adding custom styles and combining with original styles on the element.

@Andarist
Copy link
Member Author

@mycarrysun could you elaborate more on this? I'm not exactly sure what you are proposing

@mycarrysun
Copy link

mycarrysun commented Mar 13, 2020

@Andarist the goal of my feature was to add styles to all children but also allow the children to declare their own styles if necessary. Here is the component:

import { css as createEmotionClassName } from 'emotion';

export function FormAccessibleWrapper({
  children,
}) {
  return React.Children.map(children, (child) => {
    const { props: { css: childCss } = {} } = child;

    return React.cloneElement(child, {
      className: createEmotionClassName([
        styles.base,
        includeHoverStyles && styles.hover,
        includeFocusStyles && styles.focus,
        includeActiveStyles && styles.active,
        childCss,
      ]),
    });
  });
}

Originally I had tried to do:

export function FormAccessibleWrapper({
  children,
}) {
  return React.Children.map(children, (child) => {
    const { props: { css: childCss } = {} } = child;

    return React.cloneElement(child, {
      css: [
        styles.base,
        includeHoverStyles && styles.hover,
        includeFocusStyles && styles.focus,
        includeActiveStyles && styles.active,
        childCss,
      ],
    });
  });
}

It would be great to know that I needed to use the css function that emotion exports. Took a few tries and I stumbled upon the solution but it wasn't very straightforward based on the error message.

Here is an error message that would be more helpful:

You have tried to use an emotion compiled stylesheet as input to the css prop, please pass this to className instead or compose a new stylesheet by passing it into css()

Might be a better way to word the "passing it into css()" but hopefully you get my drift

louisgv pushed a commit to louisgv/emotion that referenced this pull request Sep 6, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants