Skip to content

support object literal property value shorthand #23

Description

@bloodyowl

side note : following the issue react/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 😄

Activity

  1. RReverser commented on Nov 27, 2014

    @RReverser
    Contributor

    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}} />)}
  2. bloodyowl commented on Nov 27, 2014

    @bloodyowl
    Author

    this doesn't seem to work so far

  3. RReverser commented on Nov 27, 2014

    @RReverser
    Contributor

    You probably didn't enable ES6 transformation in your transpiler.

  4. bloodyowl commented on Nov 27, 2014

    @bloodyowl
    Author

    oh, sorry, I actually did for this test.

    but is it really logical that {...{foo}} is supported when {foo} isn't?

  5. RReverser commented on Nov 27, 2014

    @RReverser
    Contributor

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

  6. denvned commented on Nov 9, 2015

    @denvned

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

  7. wmertens commented on May 6, 2016

    @wmertens

    Right now the spec is that JSXSpreadAttribute is 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.

  8. RReverser commented on May 6, 2016

    @RReverser
    Contributor

    Right now the spec is that JSXSpreadAttribute is the first attribute and is of the form { ... AssignmentExpression }.

    It's not necessarily the first.

  9. wmertens commented on May 8, 2016

    @wmertens

    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.

  10. wmertens commented on Aug 12, 2016

    @wmertens

    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.

  11. jonvuri commented on Aug 13, 2016

    @jonvuri

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

  12. merlinstardust commented on Aug 29, 2016

    @merlinstardust

    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

    const a = 1;
    const b = 2;
    ...
    <Component a b>
    

    I know that currently this actually passes in true to both a and b but I don't know why that's the case.

  13. johnste commented on Aug 30, 2016

    @johnste

    @merlinpatt I think there's a big risk of confusion to do it that way. If you add a property c which is undefined, does that still mean it would be recieved as true? Property names would take of different meaning depending on the contents of the scope they are in.

  14. wmertens commented on Aug 30, 2016

    @wmertens

    …so, is there any chance of this ever happening? What would it take, a petition, a funny youtube video, Belgian chocolate?

  15. 37 remaining items

  16. tanohzana commented on Jun 4, 2019

    @tanohzana

    @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? 🙂

  17. ljharb commented on Jun 4, 2019

    @ljharb

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

  18. jakeNiemiec commented on Jun 4, 2019

    @jakeNiemiec

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

  19. ljharb commented on Jun 4, 2019

    @ljharb

    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.

  20. nojvek commented on Jun 7, 2019

    @nojvek

    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.

  21. nojvek commented on Jun 10, 2019

    @nojvek

    #118

    ^ made a proposal for the BNF grammar change

  22. Quozzo commented on Aug 15, 2019

    @Quozzo

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

  23. anthonyhumphreys commented on Aug 21, 2019

    @anthonyhumphreys

    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} />`
    
  24. CyberCookie commented on Aug 28, 2019

    @CyberCookie

    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.
    <Component props={thing} />

  25. ljharb commented on Aug 28, 2019

    @ljharb

    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.

  26. garkin commented on Apr 17, 2020

    @garkin

    @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 })

  27. LucasUnplugged commented on Jul 25, 2022

    @LucasUnplugged

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

  28. edemaine commented on Dec 31, 2022

    @edemaine

    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.

  29. kkrivera-r7 commented on Aug 19, 2024

    @kkrivera-r7

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

  30. PartMan7 commented on Sep 10, 2024

    @PartMan7

    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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions