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

React 15+ inline styling is producing concatenated style properties from separate, unique object keys #6524

Closed
nathanmarks opened this issue Apr 15, 2016 · 6 comments

Comments

@nathanmarks
Copy link

nathanmarks commented Apr 15, 2016

Assume the following styles object is provided to a component:

const styles = {
  background: 'none',
  backgroundColor: 'red'
};

Prior to v15, this would result in (in the browser's computed styles):

background: none;
background-color: red;

In React 15+, this results in (in chrome 49+):

background: none red;

In chrome 48 it results in:

background: none;

What this means is in chrome 49+, it has a red background, but in chrome 48 it has no background.

I'm not entirely sure who/what is at fault here. Would you be able to shed some light on the change? Is this a bug or an intended feature?

@nathanmarks nathanmarks changed the title React 15+ is resulting in concatenated inline style properties React 15+ inline styling is resulting in concatenated inline style properties Apr 15, 2016
@nathanmarks nathanmarks changed the title React 15+ inline styling is resulting in concatenated inline style properties React 15+ inline styling is producing concatenated style properties from separate, different object keys Apr 15, 2016
@nathanmarks nathanmarks changed the title React 15+ inline styling is producing concatenated style properties from separate, different object keys React 15+ inline styling is producing concatenated style properties from separate (unique) object keys Apr 15, 2016
@nathanmarks nathanmarks changed the title React 15+ inline styling is producing concatenated style properties from separate (unique) object keys React 15+ inline styling is producing concatenated style properties from separate, unique object keys Apr 15, 2016
@oliviertassinari
Copy link
Contributor

oliviertassinari commented Apr 15, 2016

@nathanmarks We already faced a similar issue on the Material-UI Repository, we ended up fixing it with mui/material-ui#3124.
Chrome had a buggy implementation of Object.assign. It's fixed now with this commit.
You can follow this thread for more details mui/material-ui#2986.

I'm wondering if this isn't the same issue.
A quick fix would be no to use overlapping styles like background and background-color as suggested here #6348.

@nathanmarks
Copy link
Author

@oliviertassinari I tested with React 0.14 and React 15 with a very simple component:

const Example extends React.Component {
  render () {
    const styles = {
      background: 'none',
      backgroundColor: 'red'
    };

    return (
      <div style={styles}>Hello</div>
    );
  }
}

And in the chrome dev tools inspect element styles panel, I saw different computed values for React 0.14 and React 15

@zpao
Copy link
Member

zpao commented Apr 15, 2016

Hmm, it could be that Object.assign is at play here. I didn't think that would matter on initial render at least (I don't think we use a copy of the style object) but I'm just skimming this code path. It would make sense that the order is getting screwed up and red gets set before none.

The computed values are going to be misleading due to the use of createElement. In 14 we generated a string of markup for initial render which would look like <div style="background: none; background-color: red"></div>.

In 15 we create a DOM node and then set each style, just like we would do for updates in 14 and below. So var node = document.createElement('div'); node.style.background = 'none'; node.style.backgroundColor = 'red'; Chrome doesn't report that sequence in the computed value so you only see the final value.

So what would be interesting is if you followed the same steps as React is doing in both versions of Chrome and see what happens. http://jsbin.com/dekiyulane/edit?html,js,output

@nathanmarks
Copy link
Author

nathanmarks commented Apr 15, 2016

@zpao

Strangely I'm having difficulty reproducing this again using my simple example component (and your example), I wonder if I clicked out of browserstack before it had a chance to finish rendering completely. So @oliviertassinari may well have been correct with the Object.assign assertion.

I'm going to do some further testing -- if I end up swinging back around to React again I'll reopen this issue.

Thanks for the explanation by the way, definitely helps understand the initial render output 👍

@zpao
Copy link
Member

zpao commented Apr 15, 2016

The Object.assign issue has been pretty random and inconsistent in my experience. Thanks for checking!

@nathanmarks
Copy link
Author

nathanmarks commented Apr 16, 2016

@zpao

Figured it out. Object property iteration order is ending up different in setValueForStyles() when touched by a particular script (even though when I iterate over the styles in the createElement it still has the original order preserved).

The result is background gets iterated over after backgroundColor in chrome 48, but not in 49 (both with React 15 + our updated codebase/deps, etc...)

Now, since object property iteration order can't be guaranteed (from what I understand). That means this is definitely something we need to solve when we generate inline styles.

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

No branches or pull requests

3 participants