Skip to content

Conversation

@andrewdushane
Copy link
Contributor

@andrewdushane andrewdushane commented Dec 31, 2016

Adds a destructure destructuring option to pure-component that will destructure the props where it's safe to do so.
See the tests for use cases:
Input
Output

Needs to be tested Only works if there are no references to `this.props` by itself Would be nice if it would work for (replace) in-render destructuring
If `bar` is assigned to `this.props.bar` we need to remove that, as it's available as a destrctured arg
@cpojer
Copy link
Member

cpojer commented Jan 3, 2017

@keyanzhang is the man to review this.

@keyz
Copy link
Member

keyz commented Jan 3, 2017 via email

const ReactUtils = require('./utils/ReactUtils')(j);

const useArrows = options.useArrows || false;
const destructureEnabled = options.destructure || false;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const build = ({ functionType }) => (name, body, typeAnnotation, destructure) => {
const identifier = j.identifier(name);
const propsIdentifier = buildIdentifierWithTypeAnnotation('props', typeAnnotation);
const propsArg = [(destructure && destructureProps(j(body))) || propsIdentifier];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here it drops existing type annotations built by buildIdentifierWithTypeAnnotation.

Input:

class PureWithTypes extends React.Component { props: { foo: string }; render() { return <div className={this.props.foo} />; } }

Output:

function PureWithTypes( { foo, }, ) { return <div className={foo} />; }
const propNames = new Set();
toDestructure.replaceWith(path => {
const propName = path.value.property.name;
propNames.add(propName);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While this approach (adding names to the set while replacing) is efficient, it introduces some potential shadowing issues. For example:

Input:

class Shadowing extends React.Component { render() { let style = { color: 'black' }; return <div style={{...style, ...this.props.style}} />; } }

Output:

function Shadowing( { style, }, ) { let style = { color: 'black' }; return <div style={{...style, ...style}} />; }

I think a better way here is to scan the whole function twice (using forEach), once for identifiers and once for prop property accesses; then we can compare the two sets to see if it's possible to apply destructuring here.

),
]
);
const build = ({ functionType }) => (name, body, typeAnnotation, destructure) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: unnecessary to use a named parameter here

@slorber
Copy link

slorber commented Jan 12, 2017

hey.

Just a note as I already passed my codemod: I would have liked to use this option, but also why not using an arrow function instead of replacing the class by a real function?

@andrewdushane
Copy link
Contributor Author

andrewdushane commented Jan 12, 2017

@slorber if you use both the destructure (which will become destructuring) and useArrows options, you'll get destructured arrow functions.
useArrows is already in the master branch, so you could re-run your mod with --useArrows=true

@slorber
Copy link

slorber commented Jan 12, 2017

so bad I already did the migration, the useArrow option was not documented :)

@andrewdushane
Copy link
Contributor Author

I've put in those fixes @keyanzhang

@andrewdushane
Copy link
Contributor Author

@keyanzhang :ping:

@keyz
Copy link
Member

keyz commented Jul 10, 2017

Sorry for the late response -- somehow I missed the email notification. Thanks for the great work @andy-j-d!

@keyz keyz merged commit b162864 into reactjs:master Jul 10, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

5 participants