Skip to content
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

Proposal: destructuring #76

Open
lencioni opened this issue Mar 24, 2017 · 5 comments
Open

Proposal: destructuring #76

lencioni opened this issue Mar 24, 2017 · 5 comments

Comments

@lencioni
Copy link

Let's say you have a function that returns an object with a known shape that you want to use as props. Currently with JSX, you would use spread:

<Foo {...bar()} />

This is compiled to the following:

React.createElement(Foo, bar());

Great! Now, let's say you want to add some other props to this.

<Foo {...bar()} baz />

When compiling for React, this is compiled to the following:

var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };

React.createElement(Foo, _extends({}, bar(), { baz: true }));

Which makes sense, but the Object.assign and _extends helper code here is a bit of a bummer if you happen to do this all over the place. Granted, there are ways to minimize the helper code, but you still have the overhead of Object.assign.

It might be nice to have a way to destructure in JSX to avoid this overhead. Here's an idea:

<Foo {fizz, buzz}={bar()} baz />

could compile to something like this:

React.createElement(Foo, (_bar = bar(), { fizz: _bar.fizz, buzz: _bar.buzz, baz: true }));

JSPerf: https://jsperf.com/object-assign-vs-shenanigans/1

This might dovetail well with AssignmentExpression in JSXAttributeName (#21) which is being considered for JSX 2.0 (#65).

@jeffmo
Copy link

jeffmo commented Mar 24, 2017

I like that this helps to be precise about which props you want to spread (when not all of them).
I suspect Flow (by way of users of Flow) might benefit from this precision... cc @samwgoldman

@lencioni
Copy link
Author

And of course array destructuring could be done similarly:

<Foo [, second, third]={bar()} baz />

becomes

React.createElement(Foo, (_bar = bar(), { second: _bar[1], third: _bar[2], baz: true }));

@lencioni
Copy link
Author

And assigning to new variable names:

<Foo {fizz: fizzy, buzz: buzzy}={bar()} baz />

becomes

React.createElement(Foo, (_bar = bar(), { fizzy: _bar.fizz, buzzy: _bar.buzz, baz: true }));

@beefancohen
Copy link

I think that maybe it could support default values as well.

<Foo {fizz = 1, buzz = 2}={bar()} baz />

becomes

React.createElement(Foo, (_bar, = bar(), { fizz: _bar.fizz === undefined ? 1 : _bar.fizz, buzz: _bar.buzz === undefined ? 2 : _bar.buzz, baz: true }

Although defaultProps can (and should) be used, at least this gives feature parity with normal destructuring

@sebmarkbage
Copy link
Contributor

I think that we'll probably want to align with a proposal to general JS to do this in object literals rather than inventing our own way of doing this that then may get misaligned with a JS solution. Here is a plausible proposal that might satisfy this general use case for object literals:

https://github.com/RReverser/es-borrowed-props

We could do the same for JSX if this proposal advanced in JS.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants