-
Notifications
You must be signed in to change notification settings - Fork 47.1k
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] Add support for arrays with holes in style attribute #2196
Conversation
5357298
to
0df5b8e
Compare
If this allows us to remove all the third-party react-style libraries/mixins/preprocessors then I'm all for it! But I still think it's much more performant if you manually merge the styles outside of render and turn it into an id for |
0df5b8e
to
8a56514
Compare
Summary: See the style proposal on react-future: https://github.com/reactjs/react-future/blob/master/04%20-%20Layout/Inline%20Style%20Extension.md The goal is to enable writing CSS purely in JavaScript. We've been using this for a couple of internal projects and it's proven to be a very expressive tool. Note that this diff doesn't bring `StyleSheet.create` nor `StylePropType`. I'm keeping it simple by just allowing arbitrary arrays, objects and falsy values. Test Plan: ``` grunt test ``` Reviewers: jwalke zpao sema CC: tomocchino
The way we "corrected" This is easily extracted into a helper function (a la |
The goal is to move to a world where we don't use CSS anymore. Inline styles are actually a very good abstraction to replace most of CSS. I thought a lot about how to plug it into React and settled on extending the API just slightly. @sebmarkbage has a spread operator proposal for objects but the syntax overhead is dissuasive
Using flattenStyle is an option but is still verbose. Also, it has a big downside that going from 1 to 2 styles requires a high cognitive overhead.
Inline styles are something that's used very heavily. In the biggest project where we tried this, we have 50 React components, and 100 inline styles. In another, 30 components for 130 inline styles. |
Yes. I'd like to see a bit of discussion from @vjeux about this - I know he has ideas. If Paul has issue with this not being very DOM-ish, then maybe we can name it "styles" (plural)? |
It also makes it harder to preflatten and perform optimizations in reconciliation. |
So, the idea would be to re-write var styles = {
base: { color: 'red' },
active: { fontWeight: 'bold' }
}; into var styles = StyleSheet.create({
base: { color: 'red' },
active: { fontWeight: 'bold' }
}); which would return a value
This is strictly an optimization and we'll still need to support inline styles. So my intention is to first ship the easy but not so efficient version and then bring the infrastructure for the stylesheet. |
I could be convinced, I just want to make sure we don't get too loosey-goosey. We have a DOM story and changes like this make it much harder to say no to other changes. Let's let it simmer for a few days (I'll be on PTO anyway), get some perf numbers, and hear from others before doing anything. |
Note that we've been building two major features with this on the mobile website. We forked React and this is an attempt to converge again. |
If that is the goal, wouldn't we be better off by simply creating classes dynamically and returning those instead? (performance win too) As the class styles would have to be static anyway. |
The problem with CSS classes is that you need to control precedence, you want these to be different styles:
If you mix inline style with classes the former always have the priority over the later, even if it is placed before in
|
[Ugh. I thought I answered this before. I guess GitHub lost it during poor connections.] This data model is effectively a single record and the correct data model is to create a new record. This is why we have the If the syntax isn't palatable we should come up with something new and standardize that instead. The last thing we should do is make up our own new proprietary data structure that is not generalizable. (See my JSConf.eu talk for why that is bad.) This is a general concern with the lack of persistent immutable record types in JS which needs to be addressed at a larger scale and whatever solution we come up with should be generalizable every large immutable record type so that people don't have to come up with their own solution every time. These data types require special methods to operate on that is specific to this field. There's no automatic conversion. Our ReactChildren data structure is bad enough. We shouldn't introduce more of them. There's two parts to this proposal.
There's really no such thing as a constant because these things need to be cleaned up at some point if you have a long living app where you're able to unload modules for example. These are also not constants because they're often calculated a head of time. However, since we can assume that these objects are immutable, we can automatically or manually move declarations to the module level scope if all they depend on is branches that execute in module level scope. Thereby giving them a shared reference.
These might need a persistent object. The goal should be to get these into engines and to do that we need to start designing with that in mind. We can polyfill with an immutable record object from immutable-js or something like that. A general data structure that can later be replaced with a native record object or we can compile to support it. As it stands right now, there's not a lot of uses of these styles on the web because it is inefficient to apply inline styles in the DOM. We would need to generate classes (the precedence is solvable). I don't think we should introduce a new proprietary data type that will be difficult to upgrade a more general solution for persistent records. Not until there's an imminent need. There won't be an imminent need until the other aspects of this style model has proven itself. E.g. the application to DOM nodes, automatic reuse of constant values, class generation and the applicable programming model. By the time that happens, we may have the other language level optimizations in place. For example, in a compiler step. There is a serious abstraction leak in using a non-restricted syntax for it with possible unconstrained manipulation of the arrays. That will make it difficult to minimize all the possible misuses of this feature. So it will be difficult to undo. If we can introduce something that is more difficult to undo (such an ImmutableObject abstraction that is palatable and upgradable) then we can move forward with that instead. Or if we can prove the imminent value of this (that can't wait for other data types). |
If we use |
I'll get back to it when time is due. |
Another concern is the ability to override styles in reusable components. We need a solid pattern for this, either the dirty practice of modifying something on the component (application level override), or a way to create a copy of a component class with modifications to the styles, or both. This is unfortunate, but important for practical uses. With external style sheets this is less of an issue because you can just provide a default stylesheet which people can modify before using it, or they can override styles in their own stylesheet. Somewhat common solution is to provide a renderer for certain nodes. For example: <Form fields={fields} inputRenderer={MyInput} /> And the component would do |
@brigand I've run into this and implemented something, but there are some interesting tradeoffs. I have components that use styles based on their ref key. The top-level node is always ref=
There's logic that pushes that style object to take precedence over the internal one. It works for me, but there are some interesting cases. Maybe you want to replace the styles completely and not merge them. The nice thing is I also use the keys for conditional styles, so something like:
Will look for the key active in the styles object and apply it to |
I think the most natural solution would be CSS-like JS objects over virtual CSSOM, so that it's consistent with React's approach for HTML. |
I'm confused as to why React Native supports this (https://facebook.github.io/react-native/docs/style.html) but ReactJS does not. I thought they shared the same behavior in the areas they overlap -- which would seem to be true for the "style" prop interface of components. Or does it nowadays, and I'm just using an older version? (scared to update just to check, as last time it took some time to get the build succeeding again) |
style doesn't map to any existing properties in react native, so there was
more freedom to do something different.
ReactDOM does not support arrays here yet.
…On Thu, Feb 9, 2017 at 6:47 PM Stephen Wicklund ***@***.***> wrote:
I'm confused as to why React Native supports this (
https://facebook.github.io/react-native/docs/style.html) but ReactJS does
not. (I thought they shared behavior in the areas they overlap -- which the
"style" prop interface is an example of)
Or does it nowadays, and I'm just using an older version? (scared to
update just to check, as last time it took some time to get the build
succeeding again)
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#2196 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AAAg_QTeMsYbvyWZG7jR-CeTGTfjc1Wvks5ra8-4gaJpZM4CilgD>
.
|
Coming from React Native to React, having the ability to pass style arrays was a big plus. |
It looks like put styles in a array was enabeld in the past, but not anymore right now, is it something missed in React Fiber ? |
You can write a babel plugin like this https://github.com/giuseppeg/babel-plugin-classnames And here is https://github.com/jsu93/babel-plugin-styles/tree/styles |
Funny enough I never read this thread but I ended up implementing these ideas (except for preflattening + ids) in my library DSS https://dss-lang.com + the babel plugin above which lets you pass an array to You can find an example on the dss repo. |
Summary:
See the style proposal on react-future: https://github.com/reactjs/react-future/blob/master/04%20-%20Layout/Inline%20Style%20Extension.md
The goal is to enable writing CSS purely in JavaScript. We've been using this for a couple of internal projects and it's proven to be a very expressive tool.
Note that this diff doesn't bring
StyleSheet.create
norStylePropType
. I'm keeping it simple by just allowing arbitrary arrays, objects and falsy values.Example of use:
Test Plan:
Reviewers: jwalke zpao sema
CC: tomocchino