Repository navigation
support object literal property value shorthand #23
Description
Activity
what I'd like to be able to do with jsx is this :
{this.state.list.map((item, key) => <MyComponent {item, key} />)}
Well, you can do it like following:
{this.state.list.map((item, key) => <MyComponent {...{item, key}} />)}
Reacted by Gene Chulkov, Ioan Lucut, Nicu Barbaros, Shawn Stern, Giora Guttsait, Jed Fox, Anders D. Johnson, Stefano Savanelli, Jake Niemiec, Phil and 2 moreReacted by harold, Nate Abele, Iakov, Alexander, Kirill Alexander Khalitov, Irfan Marzuki, Daniel Rodríguez Rivero, Mikkel Davis, varHarrie, Noj Vek and 33 moreReacted by Lucasthis 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
reallylogical that{...{foo}}is supported when{foo}isn't?Reacted by Wout Mertens, Denis Nedelyaev, Adam Brodzinski, Nate Shoemaker, Ioan Lucut, Scott Fletcher, harold, Francisco, Anders D. Johnson, Mikkel Davis and 12 moreTough question. If React would start supporting
{foo},{foo, bar}, then it would be logical to support{foo: 1},{foo: 1, bar: function () {}}as well and finally we would just have object literals following tag name. Current spread-like syntax looks more logical.Reacted by Junyoung/"Clare" Jang, Matt and SukkaReacted by Noj Vek, zhangenming, cubiquitous, :Roger!, Justine Che T. Romero, Ali Söylemez, Daniel Vilela, Tyler Barnes, Mesqalito, Bruno Fantauzzi and 2 moreReacted by Matt and SukkaI 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
<Comp {propA} {propB} {propC}>should be allowed as a shorthand for<Comp propA={propA} propB={propB} propC={propC}>, because it is way easier to read and write.Reacted by Jake Crosby, harold, Weston Siegenthaler, Anders D. Johnson, Doug, Giuseppe, Scott Tolinski, Aidan Fraser, Sindre Sorhus, Mikkel Davis and 24 moreRight now the spec is that
JSXSpreadAttributeis the first attribute and is of the form{ ... AssignmentExpression }.If instead it was of the form
{ es6ObjectLiteral }it would be equally specific and parseable, and it would make tedious passing down of individual attributes a lot nicer…Note that ES6 syntax has been around for a while now and used a lot, and the fact that
{...props}is not an actual ES6 object literal expression is just plain confusing.Reacted by Haroen Viaene, Doug Orleans, Noj Vek and Lucas CastroRight now the spec is that JSXSpreadAttribute is the first attribute and is of the form { ... AssignmentExpression }.
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.
Reacted by Ron ChanOu, harold, Nate Abele, Nick Cox, Lydia Schow, Daniel Rodríguez Rivero, Noj Vek, Dom, Troy Alford, Grant Kiely and 8 moreFirst of all, the object spread operator actually isn't in
"es2015"preset proper, but still in stage 2. For teams like mine where we prefer to stick to the established standard for guaranteed maintainable code, the spread operator isn't an option for us yet, and this syntax excludes us.But also, it really does not make sense for
{...{foo, bar}}to work and for{foo, bar}not to. They both end up being{foo, bar}after being evaluated, and if you passed them to any normal function, that function wouldn't (and shouldn't) know how it got evaluated.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.
Reacted by Wout Mertens, Merlin (they/them), Ron ChanOu, Noj Vek, Dom and Lucas CastroWould 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
const a = 1; const b = 2; ... <Component a b>I know that currently this actually passes in
trueto bothaandbbut I don't know why that's the case.@merlinpatt I think there's a big risk of confusion to do it that way. If you add a property
cwhich is undefined, does that still mean it would be recieved astrue? Property names would take of different meaning depending on the contents of the scope they are in.…so, is there any chance of this ever happening? What would it take, a petition, a funny youtube video, Belgian chocolate?
Reacted by Connor Elsea, Noj Vek, Dom, Cefn Hoile, Lucas Castro, Mahesh Bansod, Bruno Fantauzzi, Lewy Blue and Wangechi Karanja37 remaining items
@ljharb would you say the same for TS and JS ? Some ES7 took time to be reimplemented in TS, such as the
includesfunction. What I think is that we need this "attribute shorthand" in JSX, so why wait for JS people to "validate" or acknowledge it...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.
Reacted by Steven, Heaven, Geoffrey Dhuyvetters, Florian Adonis, Dom and Nicky McCurdy@ljharb How would "
JavaScript language semantics should absolutely have “dibs” on anything jsx would add" work with "don't break the web"?Should
jsxusers expect future breakage?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.
Reacted by Doug, Hakim Mazouz and MesqalitoReacted by Jake NiemiecSeeing 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
<Foo {hello, world} />Rather than reading a curly ... as special spread, the curly is read as an object literal just as normal js syntax.
Transpired to
h(Foo, {hello, world})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.
Reacted by Jake Niemiec, Luděk Štěpán, Doug Orleans, Nicolas Gryman, Rory McMeekin, Iván Vázquez, zhangenming, Dom, Grant Kiely, Terence Tuhinanshu and 2 moreReacted by Jake Niemiec, Luděk Štěpán and Rory McMeekin^ made a proposal for the BNF grammar change
Reacted by Nicolas Gryman, Dom and Terence TuhinanshuI came here wondering why this wasn't possible either.
The spread operator converts an object into key value pairs, so
<Component {...props} />
would be akin to writing
<Component {key: value} />
which is converted to property-value pairs.
<Component key={value}/>It wouldn't be a reach to expect similar results from the property value shorthand syntax of
<Component {foo} />
which by the rules of the spread operator is converted to
<Component {foo: foo} />
Which is then converted to property-value pairs.
<Component foo={foo} />Reacted by Romain Le Quellec, Juan Riquelme, Aleksander Szczepanek, Dom, Bjarki Hall, ૮༼⚆︿⚆༽つ, Liam Dyer, Minae Lee, Terence Tuhinanshu, Max Syabro and 3 moreSecond this, especially for boolean props, it would be great to be able to do:
<Component {thing} />``` and have the component simply receive that value rather than `<Component thing={thing} />`Reacted by Minae LeeWhen we pass props via spread operator we actually create a loop over all the keys in a props object:
<Component {...thing} /> // loop over thing's keysSyntax proposed above eliminate unnecessary loop:
<Component {thing} /> // no loop hereWe can even accomplish it without much of syntax rewrite just by adding one more preserved property called
propsand assign property object to it.
<Component props={thing} />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.
<Component {...thing} /> // loop over thing's keysIt's a compiler task to detect a degenerate case which doesn't require loop and pass object directly.
And this is exactly how it works in any senile compiler atm. Including Typescript and Babel.<Foo {...{hello, world}} />compiles exactly to theReact.createElement("div", { hello, world })I think the real solution would be to remove boolean-true props i.e. no more
<Foo thisistrue/>, that would allow us to provide an element prop syntax that is functionally on par with object literals. I personally would probably find that preferable, but I imagine that not everyone agrees, especially considering the current legacy (although that is codemod-able). It comes down to choosing which of the two features you want, it seems you can't have both and have a truly familiar and coherent syntax. Both aren't a necessity either, languages have strengths and weaknesses, it's about balance.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
<Foo {some} {prop} />, but it sounds like it would cause the least amount of conflict with the existing behaviour of the language.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:
<Foo some prop />.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:
<div {foo}>is equivalent to<div foo={foo}><div {foo: bar}>is equivalent to<div foo={bar}><div {foo, bar: baz, ...rest}>is equivalent to<div foo={foo} bar={bar} {...rest}><div {[name]: value}>and<div [name]={value}>are equivalent to<div {...{[name]: value}}>- Getters, setters, and methods within the object literal also work (converting to
{...{ stuff }}form)
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.
Reacted by Gustavo, Fabio Spampinato, Max Coplan, Jonno Riekwel, Travis Cooper, Alexander Kachkaev, Daniel Vilela, Mahesh Bansod, Richie Davis, Tyler Barnes and 10 moreReacted by German JablonskiI would like to bump this thread and say that I would love this functionality to be present in React as well.
Reacted by Nik Rev and Dillon RieckeAs 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
<Component {prop} />=><Component prop={prop} />syntax), but despite people having discussion here, there hasn't been any attempt at targeting these features from groups that have the authority to make these decisions. JSX is exclusively a developer-side language, since no browser natively supports the syntax, which means efforts towards DX should be given weight, particularly when we're still required to write out code like this:// 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.
Reacted by Fabio Spampinato, Sanborn Hilland, Bryan Thomas, Doug Orleans, Wout Mertens, Francisco, Jon Vuri, Nicolas Gryman, David Sundqvist, Wangechi Karanja and 3 more
side note : following the issue react/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 😄