facebook / jsx

The JSX specification is a XML-like syntax extension to ECMAScript.
http://facebook.github.io/jsx/
1.97k stars 132 forks source link

support object literal property value shorthand #23

Open bloodyowl opened 9 years ago

bloodyowl commented 9 years ago

side note : following the issue facebook/react/issues/2536

what I'd like to be able to do with jsx is this :

{this.state.list.map((item, key) => <MyComponent {item, key} />)}

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 IMO

var item = "value"
return <Foo {item}/>

isn'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 :smile:

endash commented 6 years ago

All that said, #108 would seem to preclude the use here, but I'd argue that if ES6 semantics obtain enough for #108 to be implemented, then some form of this ticket—the far more common issue—should already be implemented. It wouldn't make sense for the use case in 108 to have dibs on brackets because of ES6 semantics, if in this ticket it's decided that ES6 object literal semantics needn't obtain as a consequence of similar logic.

ljharb commented 6 years ago

JavaScript language semantics should absolutely have “dibs” on anything jsx would add; confusion between JS and jsx should be considered unacceptable.

tanohzana commented 5 years ago

@ljharb would you say the same for TS and JS ? Some ES7 took time to be reimplemented in TS, such as the includes function. 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? 🙂

ljharb commented 5 years ago

@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.

jakeNiemiec commented 5 years ago

@ljharb How would "JavaScript language semantics should absolutely have “dibs” on anything jsx would add" work with "don't break the web"?

Should jsx users expect future breakage?

ljharb commented 5 years ago

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.

nojvek commented 5 years ago

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

<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.

nojvek commented 5 years ago

https://github.com/facebook/jsx/pull/118

^ made a proposal for the BNF grammar change

Quozzo commented 5 years ago

I 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} />

anthonyhumphreys commented 5 years ago

Second 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} />`
CyberCookie commented 5 years ago

When 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 keys

Syntax proposed above eliminate unnecessary loop: <Component {thing} /> // no loop here

We can even accomplish it without much of syntax rewrite just by adding one more preserved property called props and assign property object to it. `

`

ljharb commented 5 years ago

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.

garkin commented 4 years ago

@CyberCookie

<Component {...thing} /> // loop over thing's keys

It'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 the React.createElement("div", { hello, world })

LucasUnplugged commented 2 years ago

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 />.

edemaine commented 1 year ago

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.

kkrivera-r7 commented 2 months ago

I would like to bump this thread and say that I would love this functionality to be present in React as well.

PartMan7 commented 1 month ago

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 <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.