-
Notifications
You must be signed in to change notification settings - Fork 131
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
support object literal property value shorthand #23
Comments
Well, you can do it like following: {this.state.list.map((item, key) => <MyComponent {...{item, key}} />)} |
this doesn't seem to work so far |
You probably didn't enable ES6 transformation in your transpiler. |
oh, sorry, I actually did for this test. but is it |
Tough question. If React would start supporting |
Thank you for reporting this issue and appreciate your patience. We've notified the core team for an update on this issue. We're looking for a response within the next 30 days or the issue may be closed. |
I agree with @bloodyowl in that allowing spread-like syntax and not allowing object literals is not so logical. But if not object literals then at least |
Right now the spec is that If instead it was of the form Note that ES6 syntax has been around for a while now and used a lot, and the fact that |
It's not necessarily the first. |
Oh you're right, I didn't see the ending s on the recursive attribute definition. All the better, that's nicer to use and it doesn't change the specific parseability, the only thing in a tag that starts with a { is a spreadattribute. It still looks exactly like an object literal but it sadly and unnecessarily isn't. |
I keep wishing for this, every time I write intermediate components that just pass props: <MyComponent {...{key: bar, prop1, prop2}}/> just seems uglier than <MyComponent {key: bar, prop1, prop2}/> Supporting the latter syntax is essentially free, as the former syntax is just a special case of the latter. There are no parsing conflicts, no transpiling inefficiencies, … it just looks and behaves like ES6 and thus reduces astonishment. |
First of all, the object spread operator actually isn't in But also, it really does not make sense for JSX is already a series of keys and values, why can't those keys and values be expressed in a normal inline object literal? That would make perfect sense. |
Would it at all be possible / make sense to instead have this done without the object literal but still use the idea of shorthand? By that I mean, you could do this
I know that currently this actually passes in |
@merlinpatt I think there's a big risk of confusion to do it that way. If you add a property |
…so, is there any chance of this ever happening? What would it take, a petition, a funny youtube video, Belgian chocolate? |
My perspective on this:
|
Why do you feel like it's quirky, @syranide? What if we focus less on this case of property shorthand as a sugar and just talk about this idea: Any object literal expression in JSX sets its key-values as attributes on the element, without worrying about the inner syntax of the literal. We can even think of it as if the object literal attribute syntax is the "natural" JSX syntax since it is more expressive, with the HTML-attribute syntax being the sugar instead:
I feel like anyone familiar with JSX wouldn't blink much at the above, and would understand the intent and how it should behave. It also wouldn't be very surprising to then see things like this and understand what's going on:
And the spread operator is even still supported, with the same semantics:
( And as a note about your example
So if we imagine all object literals in one JSX element as just being "concatenated" these would act the same way, with left-to-right merging:
In comparison with this syntax, the current spread-operator syntax is the one that seems odd and less obvious. It's unexpected that these two expressions are not equivalent, when they are equivalent elsewhere in ES2015:
JSX peeks into the object literal expression and uses its spread operator to instead mean "spread attributes over the JSX element" rather than spreading properties over the object literal, and that behavior isn't very obvious without a prior explanation. And even if it made sense, again, the spread operator is nonstandard in ES2015 and still subject to change, and requires an extra plugin to work. Also, I'm not sure I understand this, @syranide:
Why? Why couldn't you mix object expressions and normal attributes? All I said above is assuming that should be possible but perhaps I'm missing something. |
@jrajav I was commenting on the two different ideas presented separately.
Anyway, both are fine, I even proposed switching to the first one early on, IMHO the most important thing about JSX is that it adds visual clarity to hierarchies, not that it looks like XML. Reusing the native object literal syntax makes a ton of sense technically. However, having both doesn't really make sense. A language isn't about having multiple ways to do the exact same thing based on preference, it's about having a common language to "speak". Also, worth noting that the object literal syntax may not lend itself as well to spanning multiple lines and in a sense it's also kind of illogical why the braces are in the syntax to begin with, they aren't necessary for anything, they just become fluff from a technical perspective (but that's a separate discussion and there may be reasons why it makes sense):
I think even the spread syntax that JSX has now is kind of weird, but it's probably the only really logical syntax for it given the current syntax of JSX. If
If the syntax was In summary, I largely agree that the object literal syntax is preferable in many ways, practically and technically, but that syntax explicitly competes with a syntax already decided on by JSX. It makes sense having competing languages implementing alternative syntaxes. It does not make sense having it in JSX, JSX is an explicit choice with an opinionated syntax. I can also imagine a few additional tweaks to the syntax that would further make it less XMLy and more JSy, which may make sense given that HTML is far from the only frontend out there. PS. This is my opinion/perspective and may not be shared by everyone else. |
@syranide A lot of what you're saying makes sense and I can see where you're coming from. I do support the idea of having one way to do something, where it makes sense. Just to reiterate what my main pain point is, it's less to do with the spread operator that you focused on (which I honestly don't care much about, I prefer explicitly passing each property for a robust interface). It is more that there isn't a non-ugly way to apply local symbols to an element without repetition. There are only two alternatives:
Allowing arbitrary object literal expressions would solve this neatly and also enable other useful patterns like computed keys. As for the notion of competing syntaxes, that's one way to look at it. But another way to look at it as JavaScript vs. the JSX sugar for the JavaScript. Elsewhere in JSX, Granted, this would make more sense if the syntax was instead |
@jrajav Yeah, if that's what you want then spread really isn't a good fit, no doubt. But I'd say the proposed syntax seems like an overreach for trying to accomplish just that. So in my opinion, as I said, I think the real solution would be to remove boolean-true props i.e. no more Going off on a tangent, if we imagine a future where ECMA wants to incorporate these "elements" into JS, then it's important to remember that they may chose a very different version of JSX. The JSX we're discussing here is simply one possible proposal in that scenario. But if this JSX were to be seriously considered it also has to be "rigorously designed", adding small nice-to-have features with large-scope syntax changes/side-effects seems like a quick way to shut that door, there needs to be a coherent vision for the language, that includes a balanced trade-off.
IMHO, that's the wrong way to look at it, "JSX-elements" is a true citizen of this language, there is no exiting back to JS. Expression values can be JSX-elements and JSX-element property values can be expressions. JSX-elements is part of the language grammar like everything else, it's not special, just more syntax rules. Put differently, if I would design JSX I would design the syntax to more along the lines of the following, to be more comparable to JS syntax.
My overall point is; consider if you made the same syntax extension to the current JS object literal syntax, adding a separate but equivalent syntax to achieve almost exactly the same thing and a nice-to-have-feature. It doesn't seem like a good idea. |
@syranide I agree with you that the syntax should not become overly sugary and complex, but our point is that the current syntax is a subset of the proposed syntax, given the stage-2-but-ready-for-stage-3 object spread operator. That is to say, Furthermore, adding JSX syntax to ECMA seems improbable, and if it happens in has only 2 outcomes:
So I don't think this possibility should inform this decision. For me it is clear-cut: Make JSX more obvious at 0 cost, or not. |
Yeah @wmertens, that's still a pertinent point - again, it would make a lot of sense to simply support any sort of object literal expression since that's what the current syntax looks like anyway and it would be perfectly compatible with it. Nothing crazy is even being added, just making the current implementation make more sense. And as for trying to do this in the "native" property-value syntax as you're proposing @syranide, I just want to point out that that would interfere slightly with applying attributes to the elements, for instance |
As @jrajav pointed out, someone with a background in HTML would expect I think the problem here is that JSX too much tries to look like HTML. If it were more obvious that JSX is more JS rather than HTML... For example (note colons and commas):
The only problem I can see with the above syntax is that the closing bracket |
Not much input on this for a while... would a pull request be welcome here? |
The problem here is that one side (contra this issue) believes that It's not a missing PR issue, we have the technology. On Wed, Oct 12, 2016 at 8:44 PM Jonathan Rajavuori [email protected]
|
@ljharb would you say the same for TS and JS ? Some ES7 took time to be reimplemented in TS, such as the This issue was open back in 2014. Can you guys merge this already, please? 🙂 |
@tanohzana yes, i would, and i believe the TS core team now regrets shipping nonstandard proposed features, and has a policy to never do it again. |
@ljharb How would " Should |
given that jsx is always transpiled, yes, they absolutely could. jsx isn’t the web, just like typescript and coffeescript aren’t the web - thus while breakages should be minimized to avoid pain, they are certainly acceptable. |
Seeing that this issue had been open for 5 years, what is the hold back? We have issues about this in react, typescript and babel. Object spread syntax and object shorthand syntax is now a common place in all evergreen browser js engines now. The transformation is simple enough too
Rather than reading a curly ... as special spread, the curly is read as an object literal just as normal js syntax. Transpired to Since the js object literal can contain a spread e.g {...props}, This shouldn’t be a breaking change. It just makes jsx elegant and powerful with less boiler plate. There’s really nothing new to learn for js devs. It works as you’d expect it too since it’s good old object literal passed as an attribute. Should we be creating Babel and typescript proposal PRs as a sample implementations ? Someone with authority please help move this forward. |
^ made a proposal for the BNF grammar change |
I came here wondering why this wasn't possible either. The spread operator converts an object into key value pairs, so It wouldn't be a reach to expect similar results from the property value shorthand syntax of |
Second this, especially for boolean props, it would be great to be able to do:
|
When we pass props via spread operator we actually create a loop over all the keys in a props object: Syntax proposed above eliminate unnecessary loop: We can even accomplish it without much of syntax rewrite just by adding one more preserved property called |
That would break anyone with a props prop; iterating over an object with a small number of keys - like less than a million - isn’t likely to have significant perf impact as compared to manually passing the same number of props. |
It's a compiler task to detect a degenerate case which doesn't require loop and pass object directly.
|
I think @syranide has made some very valid points, so my (imaginary) vote goes to his proposal; not only would it be even less verbose than Yes, this would be a breaking change, and a pain in the ass — but a pain in the ass ONCE, and thereafter we'd have this amazingly succinct syntax: |
For those interested in this feature, there's a new language Civet that transpiles to JSX/TSX and which supports (in addition to most ECMAScript and vanilla JSX) arbitrary object literals as attributes:
The idea is to enable all the convenient syntax we want, while transpiling to regular JSX so it works in any JSX system, including TypeScript. There's also already a VSCode LSP (though not as robust as TypeScript's), so you get hover hints and squigglies and all that, even with the new syntax. |
I would like to bump this thread and say that I would love this functionality to be present in React as well. |
As we draw nearer and nearer to the ten-year mark of this, I'm confused as to why there hasn't been any attempt by Facebook to come to a decision on this. We've had multiple fairly-sound suggestions (personally I'm partial to the non-breaking and minimal // Actual code from a codebase I work on
<PostCardView
widgetViewState={widgetViewState}
isVisible={isVisible}
detailCount={detailCount}
requestGroupingDepth={requestGroupingDepth}
sizeVariant={sizeVariant}
variant={variant}
overrides={overrides}
widgetVariant={widgetVariant}
onPageChange={onPageChange}
currentPage={currentPage}
totalCount={totalCount}
onCardSelect={onPostCardSelect}
pageSize={pageSize}
numColumns={numColumns}
currency={context.currency}
/> Compare this to being written with one-entry punning: <PostCardView
{widgetViewState}
{isVisible}
{detailCount}
{requestGroupingDepth}
{sizeVariant}
{variant}
{overrides}
{widgetVariant}
{onPageChange}
{currentPage}
{totalCount}
onCardSelect={onPostCardSelect}
{pageSize}
{numColumns}
currency={context.currency}
/> or with multi-entry punning: <PostCardView
{
widgetViewState,
isVisible,
detailCount,
requestGroupingDepth,
sizeVariant,
variant,
overrides,
widgetVariant,
onPageChange,
currentPage,
totalCount,
pageSize,
numColumns
}
onCardSelect={onPostCardSelect}
currency={context.currency}
/> Single-entry punning has no contextual differences from the original code (a reader would understand it exactly as easily), while multi-entry punning is close to the existing prop spread syntax and seems to group the punned props separately from the other props (an existing case with the current spread syntax). Regardless, it would be a blessing to able to use single-entry shorthands in props the way we do with ES6 object literals, if only because it's a boon to DX at no cost whatsoever to either compatibility or semantics. |
side note : following the issue facebook/react/issues/2536
what I'd like to be able to do with jsx is this :
I know it's not to be considered a big syntax issue, its just sugar, but it seems logical to me that after supporting the spread operator, as this other ES6 feature is supported by jstransform/jsx
as @sebmarkbage said in the related react issue, the
<Foo item />
syntax is supported for boolean attributes, but IMOisn't that confusing as it is going to get supported by various browsers soon, and developers will have to know it.
so now, I think it's all about discussing this proposal 😄
The text was updated successfully, but these errors were encountered: