-
Notifications
You must be signed in to change notification settings - Fork 48.8k
Allow className to be an array of strings #1198
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
Conversation
* @param {array} className | ||
* @return {string} the result className string | ||
*/ | ||
function joinClassNameArray(className) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why are you not just using "joinClasses"?
Shouldn't we allow objects as well then? Also, 👍 Kind of a side-note, wouldn't the same thing be useful for style as well? |
@cpojer |
Spoke with @chenglou in chat a bit, and he seemed to agree. I feel like supporting only arrays and strings, but not objects ( Sure, the cc @zpao |
FIxes facebook#1179. `className={['a', null, 'b']}` becomes 'a b'. This allows you to do `className{['a'].concat(this.props.className)}` Note that nested arrays are current forbidden.
Is this the return of |
The fact that |
It should be called classList since this corresponds to the classList DOM property. That also allows an incremental upgrade path. This should use the same type check as concat, namely it should not do an Array.isArray check but rather allow array like objects, and later iterators. if (typeof n === 'string' || typeof n === 'number' || typeof n === 'boolean') {
// string
} else if (n == null) {
// empty
} else {
// array like
} Otherwise it has different semantics than the proposed combinator syntax:
This also excludes the object notation of classSet but that has other issues (objects as map is bad, mkay) and is difficult to statically type. We do use similar features in a helper but this has it's own static analysis. You can't use something like closure compiler to minify classnames. That would be dangerous without having the same logic applied to your CSS files. I'd like properties to be compatible with generic deep merging functions so that we can use or add language features for this. It's not clear whether we should even allow both strings/arrays or just arrays because we're not sure we can express this union type well in common type systems. Recursive union types are even less common which is why we'd like to wait on nested arrays. Additionally when this is used with a plain deep merge, it's not clear how you merge a string and an array unless we assume that such values are concatenated in a merge. You also can't merge two strings. That would suddenly mean that two strings are not equivalent to two arrays. The only valid data structure here is an ES6 Set. Anything else is just sugar which has to pull it's weight. |
@sebmarkbage An idea is perhaps to implement |
Are we replacing className with classList? If not, transferring props manually gets hairy because you don't know which property actually holds the classes (and what if you specify both?). Honestly, these don't feel that different to me:
so I'm in favor of leaving things as-is. |
The idea is to replace it, yes. |
@zpao @sebmarkbage What's happening here? |
tl; dr version is that transforming all these to array is too expensive internally |
Let's have this discussion in react-future so that it's consistent with other plans. |
👍 for the ability to pass in |
We're not planning to do this for now so I'm going to close it out – we can always reopen later if we do want it. |
I preferred the passing an array approach, rather than plopping a load of strings in an attribute and joining them together with spaces. If any of the items in the array is not a valid string, that item won't be added to the classes. |
FIxes #1179.
className={['a', null, 'b']}
becomes 'a b'.This allows you to do
className={['a'].concat(this.props.className)}
.Note that nested arrays are currently forbidden.