GithubHelp home page GithubHelp logo

react-codemod's Introduction

React Codemods Build Status

This repository contains a collection of codemods to help update React apps.

All codemods, whether you use the codemod CLI command or react-codemod, are free and open source, with the source code available in this repository.

Usage

We recommend using the codemod command for an enhanced experience and better support.

npx codemod <framework>/<version>/<transform> --target <path> [...options]

  • transform - name of transform, see available transforms below.
  • path - directory to transform

Check codemod docs for the full list of available commands.

For the legacy react-codemod command, see LEGACY.md.

Available Codemods

All React codemods are also available in the Codemod Registry.

remove-context-provider

Converts Context.Provider JSX opening and closing elements into Context.

npx codemod react/19/remove-context-provider --target <path>

remove-forward-ref

Removes usages of forwardRef.

npx codemod react/19/remove-forward-ref --target <path>

use-context-hook

Replaces usages of React.useContext(...) with React.use(...).

npx codemod react/19/use-context-hook --target <path>

replace-act-import

Updates act import path from react-dom/test-utils to react.

npx codemod react/19/replace-act-import --target <path>

replace-string-ref

Replaces deprecated string refs with callback refs.

npx codemod react/19/replace-string-ref --target <path>

replace-use-form-state

Replaces usages of useFormState() to use useActionState().

npx codemod react/19/replace-use-form-state --target <path>

replace-reactdom-render

Replaces usages of ReactDom.render() with createRoot(node).render().

npx codemod react/19/replace-reactdom-render --target <path>

create-element-to-jsx

Converts calls to React.createElement into JSX elements.

npx codemod react/create-element-to-jsx --target <path>

error-boundaries

Renames the experimental unstable_handleError lifecycle hook to componentDidCatch.

npx codemod react/error-boundaries --target <path>

findDOMNode

Updates this.getDOMNode() or this.refs.foo.getDOMNode() calls inside of React.createClass components to React.findDOMNode(foo). Note that it will only look at code inside of React.createClass calls and only update calls on the component instance or its refs. You can use this script to update most calls to getDOMNode and then manually go through the remaining calls.

npx codemod react/findDOMNode --target <path>

manual-bind-to-arrow

Converts manual function bindings in a class (e.g., this.f = this.f.bind(this)) to arrow property initializer functions (e.g., f = () => {}).

npx codemod react/manual-bind-to-arrow --target <path>

pure-component

Converts ES6 classes that only have a render method, only have safe properties (statics and props), and do not have refs to Functional Components.

The wizard will ask for 2 options -

  • Use arrow functions?: converts to arrow function. Converts to function by default.
  • Destructure props?: will destructure props in the argument where it is safe to do so.
npx codemod react/pure-component --target <path>

pure-render-mixin

Removes PureRenderMixin and inlines shouldComponentUpdate so that the ES2015 class transform can pick up the React component and turn it into an ES2015 class. NOTE: This currently only works if you are using the master version (>0.13.1) of React as it is using React.addons.shallowCompare

npx codemod react/pure-render-mixin --target <path>
  • The wizard will ask to optionally override mixin-name, and look for it instead of PureRenderMixin. Note that it is not possible to use a namespaced name for the mixin. mixins: [React.addons.PureRenderMixin] will not currently work.

React-PropTypes-to-prop-types

Replaces React.PropTypes references with prop-types and adds the appropriate import or require statement. This codemod is intended for React 15.5+.

npx codemod react/React-PropTypes-to-prop-types --target <path>
  • In addition to running the above codemod you will also need to install the prop-types NPM package.

rename-unsafe-lifecycles

Adds UNSAFE_ prefix for deprecated lifecycle hooks. (For more information about this codemod, see React RFC #6)

npx codemod react/rename-unsafe-lifecycles --target <path>

react-to-react-dom

Updates code for the split of the react and react-dom packages (e.g., React.render to ReactDOM.render). It looks for require('react') and replaces the appropriate property accesses using require('react-dom'). It does not support ES6 modules or other non-CommonJS systems. We recommend performing the findDOMNode conversion first.

npx codemod react/react-to-react-dom --target <path>
  • After running the automated codemod, you may want to run a regex-based find-and-replace to remove extra whitespace between the added requires, such as codemod.py -m -d src --extensions js '(var React\s*=\s*require\(.react.\);)\n\n(\s*var ReactDOM)' '\1\n\2' using https://github.com/facebook/codemod.

React-DOM-to-react-dom-factories

Converts calls like React.DOM.div(...) to React.createElement('div', ...).

npx codemod react/React-DOM-to-react-dom-factories --target <path>

ReactNative-View-propTypes

Replaces View.propTypes references with ViewPropTypes and adds the appropriate import or require statement. This codemod is intended for ReactNative 44+.

npx codemod react/ReactNative-View-propTypes --target <path>

update-react-imports

As of Babel 7.9.0, when using runtime: automatic in @babel/preset-react or @babel/plugin-transform-react-jsx, you will not need to explicitly import React for compiling jsx. This codemod removes the redundant import statements. It also converts default imports (import React from 'react') to named imports (e.g. import { useState } from 'react').

The wizard will ask for 1 option -

  • Destructure namespace imports as well?: If chosen, namespace imports like import * as React will also be converted. By default, it's false, so only default imports (import React) are converted.
npx codemod react/update-react-imports --target <path>

Support and Contributing

The scripts in this repository are maintained by the React team in collaboration with the Codemod.com team.

If you want to contribute, you're welcome to submit a pull request.

License

react-codemod is MIT licensed.

react-codemod's People

Contributors

acdlite avatar alangpierce avatar bvaughn avatar cpojer avatar dependabot[bot] avatar dmytrohryshyn avatar doytch avatar exkazuu avatar flarnie avatar gaearon avatar jsnmoon avatar keyz avatar lencioni avatar lunaruan avatar manixate avatar mkozmin avatar mohab-sameh avatar oliviertassinari avatar paramaggarwal avatar piperchester avatar realetive avatar reergymerej avatar relekang avatar rickhanlonii avatar simison avatar skovy avatar thesavior avatar threepointone avatar turadg avatar zpao avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

react-codemod's Issues

React-PropTypes to prop types: Transformation Error: Cannot read property 'name' of undefined

I ran:

jscodeshift -t transforms/React-PropTypes-to-prop-types.js ../project/src/

It this error on almost every file:

 ERR ../project/src/WebAPI/application.js Transformation error
TypeError: Cannot read property 'name' of undefined
    at /home/user/react-codemod/transforms/React-PropTypes-to-prop-types.js:91:7
    at Array.filter (native)
    at Collection.filter (/home/user/.config/yarn/global/node_modules/jscodeshift/dist/Collection.js:65:46)
    at removeDestructuredPropTypeStatements (/home/user/react-codemod/transforms/React-PropTypes-to-prop-types.js:90:6)
    at module.exports (/home/gio/react-codemod/transforms/React-PropTypes-to-prop-types.js:163:22)
// application.js
import { callApi } from './api'

export const details = ({
    ID,
    hash,
    page,
}) => callApi('application_view', {
    params: {
        id,
       hash,
       page,
    },
})

export const add = () => {}
export const search = (params) => callApi('application_search', { params })

results:

74 errors
0 unmodified
292 skipped
0 ok
Time elapsed: 1.808seconds 

I use babel-loader with this config:

['react', 'stage-1', ["env", { "targets": { "chrome": 56 }}]]

but as jscodeshift --babel flag defaults to true, I think this shouldn't be an issue.

Build Warning

Thanks for updating the test suite. There is currently a build warning:

Running 1 test suite...class-test.js: `MyComponent4` was skipped because of invalid field(s) `foo` on the React component. Remove any right-hand-side expressions that are not simple, like: `componentWillUpdate: createWillUpdate()` or `render: foo ? renderA : renderB`.

getInitialState isn't transformed into constructor this.state

Before:

let WorkspaceItemView = React.createClass({
  displayName: 'WorkspaceItemView',

  getInitialState() {
    return {
      workspaceItemManager: this._getWorkspaceItemManager(this.props.id),
      workspaceItemStore: this._getWorkspaceItemStore(this.props.id)
    };
  },
});

After: (that's how it works now)

class WorkspaceItemView extends React.Component {
  static displayName = 'WorkspaceItemView';

  state = {
    workspaceItemManager: this._getWorkspaceItemManager(this.props.id),
    workspaceItemStore: this._getWorkspaceItemStore(this.props.id)
  };
}

But it should be this:

class WorkspaceItemView extends React.Component {
  static displayName = 'WorkspaceItemView';

  constructor(props) {
    super(props);

    this.state = {
      workspaceItemManager: this._getWorkspaceItemManager(this.props.id),
      workspaceItemStore: this._getWorkspaceItemStore(this.props.id)
    };
  }
}

Pure component transform transforms classes with class properties initializers

This class that is using class property initializers

import React, { PropTypes } from 'react';

export default class StringControl extends React.Component {
  handleChange = (e) => {
    this.props.onChange(e.target.value);
  };

  render() {
    return <input type="text" value={this.props.value || ''} onChange={this.handleChange} />;
  }
}

StringControl.propTypes = {
  onChange: PropTypes.func.isRequired,
  value: PropTypes.node,
};

gets transformed to:

import React, { PropTypes } from 'react';

export default function StringControl(props) {
  return <input type="text" value={props.value || ''} onChange={this.handleChange} />;
}

StringControl.propTypes = {
  onChange: PropTypes.func.isRequired,
  value: PropTypes.node,
};

It should not.

class.js complains about deprecated API calls that are not used with React

Did a dry run and got the following message:

Overview was skipped because of deprecated API calls. Remove calls to getDOMNode, isMounted, replaceProps, replaceState, setProps in your React component and re-run this script.

I do indeed use replaceState, but the context is history.replaceState (https://developer.mozilla.org/en-US/docs/Web/API/History_API), not React, so I believe there should not be a problem, the function names just happen to be the same.

React.DOM.div not transformed

I noticed that this will transform React.createElement, but not React.DOM.div, which is just a convenience wrapper. I have a large codebase that I'm going to need to transform very soon and it's all using React.DOM.div (or span, a, etc). It sounds like it would be easy to make that work the same as React.createElement. What do you think?

PureComponent doesn’t work with React.Component destructured

We use

import React, { PropTypes, Component } from 'react';

export default class Foo extends Component {

and the PureComponent transform skips all of these. Even if this doesn't get fixed its worth noting here in case someone else is wondering why all their files are being skipped.

pure-component does not check for refs

A component can only be converted into a stateless component if it does not use refs on its children. The current codemod does not check for it.
Still amazed by these codemods, but this could be a great improvement...

Buggy conversion

MyComponent.jsx:

const React = require("react");

const MyComponent = React.createClass({
  render: function () {
    return (
      <label title={(true ? "T1" + "β€’" : "T2") + "T3"} />
    );
  },
});
jscodeshift -t ../../react-codemod/transforms/class.js MyComponent.jsx

output:

const React = require("react");

class MyComponent extends React.Component {
  render() {
    return (
      <label title={(((true ? "T1" + "β€’" : : 2") ))+ "T3"} />
    );
  }
}

"react/sort-comp" regexes are ignored

Looks like regular expression values in this eslint property are ignored. For example:

"react/sort-comp": [2, {
  order: [
    "/^render/",
    "/^on/",
    "everything-else"
  ]
}]

gives the same output as

"react/sort-comp": [2, {
  order: [
    "everything-else"
  ]
}]

findDOMNode script

Why does the script convert
this.refs.injectButton.getDOMNode().focus();

into
React.findDOMNode(this.refs.injectButton).focus()

My understanding of the changes to refs is that the original code could be transformed to
this.refs.injectButton.focus()
which if equivalent functionally seems like a better solution. In the docs it even mentions that using findDOMNode() will be unnecessary in most cases.

Was there a specific case you are guarding against to take the more conservative approach?

Thanks

TypeError: Cannot read property 'parent' of undefined

I have some components that transform incorrectly as blow:

TypeError: Cannot read property 'parent' of undefined
    at addPropTypesImport (/Users/ltchronus/Documents/workspace4air/react-codemod/transforms/React-PropTypes-to-prop-types.js:95:7)
    at module.exports (/Users/ltchronus/Documents/workspace4air/react-codemod/transforms/React-PropTypes-to-prop-types.js:182:5)

My component example is

import React, { Component, PropTypes } from 'react';
import Message from './Message';
if (process.env.BROWSER) {
  require('./style/index.scss'); // eslint-disable-line
}
...

related code

function addPropTypesImport(j, root) {
  if (useImportSyntax(j, root)) {
    const importStatement = j.importDeclaration(
      [j.importDefaultSpecifier(j.identifier('PropTypes'))],
      j.literal('prop-types')
    );

    const path = findImportAfterPropTypes(j, root);

    j(path).insertBefore(importStatement);
  } else {
    const requireStatement = useVar(j, root)
      ? j.template.statement`var PropTypes = require('prop-types');\n`
      : j.template.statement`const PropTypes = require('prop-types');\n`;
    // I have require but don't use require to PropTypes
    const path = findRequireAfterPropTypes(j, root) ;

    j(path.parent.parent).insertBefore(requireStatement);
  }
}

sort-comp is not working

Hi, when I run sort-comp transformation, it throws following error:

Error: Cannot read config package: eslint-config-airbnb
Error: Cannot find module 'eslint-config-airbnb'
Referenced from: C:\projects\client\.eslintrc
    at Function.Module._resolveFilename (module.js:440:15)
    at Function.Module._load (module.js:388:25)
    at Module.require (module.js:468:17)
    at require (internal/module.js:20:19)
    at loadPackage (C:\projects\react-codemod\node_modules\eslint\lib\config\config-file.js:168:16)
    at loadConfigFile (C:\projects\react-codemod\node_modules\eslint\lib\config\config-file.js:212:1
8)
    at load (C:\projects\react-codemod\node_modules\eslint\lib\config\config-file.js:385:18)
    at C:\projects\react-codemod\node_modules\eslint\lib\config\config-file.js:326:36
    at Array.reduceRight (native)
    at applyExtends (C:\projects\react-codemod\node_modules\eslint\lib\config\config-file.js:309:28)

I've run npm install within react-codemod directory but it didn't help.

sort-comp customization

It would be nice to pick up the specific sort order defined in .eslintrc if not provided through the CLI options before falling back to the airbnb order.

Debugging skipped files

Is there a way I can see why my files are being skipped on the create-element-to-jsx transform? I tried using astexplorer but had no luck. Any advice would be appreciated. Thanks.

The output shows:

Processing 1 files...
Spawning 1 workers...
Sending 1 files to free worker...
All done.
Results:
0 errors
0 unmodified
1 skipped
0 ok

The script skips files that have mixins in them

When running this command:
jscodeshift -t ~/react-codemod/transforms/class.js filename.jsx

For the files that have mixins in them I get:
filename.jsx: 'Component' was skipped because of mixins.

although the component is defined with React.createClass() and the script should create ES2015 classes.

How should I still use the script and work around mixins?

create-element-to-jsx doesn't handle props objects

The create-element-to-jsx transform attempts to make replacements like this:

-    return React.createElement(Constructor, props);
+    return <Constructor />;

Expected:

-    return React.createElement(Constructor, props);
+    return <Constructor {...props} />;

`prop-types` codemod fails for explicit, nested destructuring

Given a PropTypes import that looks like this:

const {
    PropTypes: {
        shape,
        bool,
        number,
        string
    }
} = React

the prop-types codemod will insert import PropTypes from 'prop-types'; but will remove the destructuring assignment completely, leaving shape, bool, number, and string undefined.

create-element-to-jsx: All files being skipped, even though react is included

not sure why but all my code is being skipped over without explantion

this is how I call the command

jscodeshift -t react-codemod/transforms/create-element-to-jsx.js dealroom/assets/jsx/core/Dialog.js

here is a sample of one of my files that is being skipped

import React from 'react';
import ReactDOM from 'react-dom';

var Dialog = React.createClass({
    
    getInitialState(){

        return {
            show: false,
            onConfirm: null,
            onCancel: null,
            onBackgroundClick: null,
        }

    },

    render(){
        return null;
    },

    showDialogBox(onConfirm, onCancel, onBackgroundClick){
        this.setState({
            show: true,
            onConfirm: onConfirm,
            onCancel: onCancel,
            onBackgroundClick: onBackgroundClick,
        })
    },

    hideDialogBox(){
        this.setState({
            show: false,
            onConfirm: null,
            onCancel: null
        })
    },

    _onConfirm(){
        if(this.state.onConfirm){
            this.state.onConfirm()
            
        }
    },

    _onCancel(){
        if(this.state.onCancel){
            this.state.onCancel()
            
        }
    },
    _onBackgroundClick(){
        if(this.state.onBackgroundClick){
            this.state.onBackgroundClick()
        }
    },


    _renderDialog(){

        const {show} = this.state;
        
        var className = 'toast dialog';
        
        

        var btn1_class = 'btn-primary';
        var btn2_class = 'btn-error';
        if(this.props.reverseBtnColor){
            btn1_class = 'btn-error';
            btn2_class = 'btn-primary';
        }

        ReactDOM.render(
            <div className='toast-container dialog-container'>
                {show?
                    <div>
                        <div className={className}>
                            <div>
                                {this.props.children} 
                            </div>
                            <div className='btns'>
                                <a className={'btn ' + btn1_class} onClick={this._onConfirm}>
                                    {this.props.confirm_text}
                                </a>
                                <a className={'btn ' + btn2_class} onClick={this._onCancel}>
                                    {this.props.cancel_text}
                                </a>
                            </div>
                                
                        </div>
                        <div className='waiting-overlay' onClick={this._onBackgroundClick}/>
                    </div>
                    :null
                }
                
             </div>
        , this.portal)
    },

    componentDidMount(){
        this.portal = document.createElement('toast');
        document.getElementById('portal').appendChild(this.portal);


        this._renderDialog(this.props);
        
    },

    componentWillReceiveProps(new_props){
        this._renderDialog(new_props);
    },
    componentDidUpdate(){
        this._renderDialog(); 
    },

    componentWillUnmount(){
        ReactDOM.unmountComponentAtNode(this.portal);
    }
});

export default Dialog

output

Processing 1 files...
Spawning 1 workers...
Sending 1 files to free worker...
All done.
Results:
0 errors
0 unmodified
1 skipped
0 ok

"Unknown encoding" error

I've tried saving my files in various encodings both in Sublime Text and by converting using iconv but I get encoding errors every time:

MacOS 10.11.3, node 5.7.0, npm 3.6.0

jscodeshift path/to/my/file.jsx -v 2 -t ~/react-codemod/transforms/sort-comp.js 
Processing 1 files... 
Spawning 1 workers...
Sending 1 files to free worker...
buffer.js:638
          throw new TypeError('Unknown encoding: ' + encoding);
          ^
TypeError: Unknown encoding: path/to/my/file.jsx
    at Buffer.write (buffer.js:638:17)
    at fromString (buffer.js:113:26)
    at new Buffer (buffer.js:58:12)
    at createWriteReq (net.js:723:38)
    at WriteStream.Socket._writeGeneric (net.js:675:11)
    at WriteStream.Socket._write (net.js:698:8)
    at doWrite (_stream_writable.js:301:12)
    at writeOrBuffer (_stream_writable.js:287:5)
    at WriteStream.Writable.write (_stream_writable.js:215:11)
    at WriteStream.Socket.write (net.js:624:40)

PropTypes transformation completely broken?

I'm trying to run the PropTypes transformation on my code base but the only file it (wrongly) updates is a file containing a single propType specification:

- import { PropTypes } from 'react';
+ import 'react';
export const SEPARATOR = 'separator';

export default {
  type: PropTypes.oneOf([SEPARATOR]),
  value: PropTypes.any,
  label: PropTypes.string,
};

All my other files are simply ignored (they are very basic components):

Processing 17 files...
Spawning 3 workers...
Sending 6 files to free worker...
Sending 6 files to free worker...
Sending 5 files to free worker...
All done.
Results:
0 errors
0 unmodified
17 skipped
0 ok

What happens?

Cannot read property 'name' of undefined, prop-types transformation

I have many components for which prop-types transformation happening correctly, but for other components its failing with following error

TypeError: Cannot read property 'name' of undefined
    at /Users/z013mrq/react-codemod/transforms/React-PropTypes-to-prop-types.js:91:7
    at Array.filter (native)
    at Collection.filter (/Users/z013mrq/.nvm/versions/node/v6.9.0/lib/node_modules/jscodeshift/dist/Collection.js:65:46)
    at removeDestructuredPropTypeStatements (/Users/z013mrq/react-codemod/transforms/React-PropTypes-to-prop-types.js:90:6)
    at module.exports (/Users/z013mrq/react-codemod/transforms/React-PropTypes-to-prop-types.js:163:22)

One such component code example is

import React from 'react';
import Link from '../Link';

const Breadcrumb = ({ links }) => (
  <div itemType="http://schema.org/breadcrumb" itemProp="breadcrumb">
    ......
  </div>
);

Breadcrumb.propTypes = {
  links: React.PropTypes.arrayOf(
    React.PropTypes.shape({
      title: React.PropTypes.string.isRequired,
      href: React.PropTypes.string
    })
  ).isRequired
};

export default Breadcrumb;

Help!

"Cannot read property 'Symbol(Symbol.iterator)' of undefined"

Wasn't sure if I should report this here or with the jscodemod folks. I ran npm -g list jscodeshift which installed the latest jscodeshift, then tried running:

jscodeshift -t ~/Downloads/react-codemod-master/transforms/pure-render-mixin.js ./ -d -p

Which gave me the following error:

No files selected, nothing to do. 
(node:1598) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 3): TypeError: Cannot read property 'Symbol(Symbol.iterator)' of undefined

Possible separate issue (unsure): I tried running it on a specific file, ./Components/App.jsx, instead of a ./ path, and I got the following output:

Processing 1 files... 
Spawning 1 workers...
Running in dry mode, no files will be written! 
Sending 1 files to free worker...
 ERR ./Components/App.jsx Transformation error
Error: You cannot call "get" on a collection with no paths. Instead, check the "length" property first to verify at least 1 path exists.
    at Error (native)
    at Collection.get (/usr/local/lib/node_modules/jscodeshift/dist/Collection.js:190:13)
    at deletePureRenderMixin (/Users/ruben/Downloads/react-codemod-master/transforms/pure-render-mixin.js:159:54)
    at removePureRenderMixin (/Users/ruben/Downloads/react-codemod-master/transforms/pure-render-mixin.js:180:7)
All done. 
Results: 
1 errors
0 unmodified
0 skipped
0 ok
Time elapsed: 1.130seconds

For the record, I'm on node v6.7.0, React 15.3.2, and I just downloaded react-codemod.

TypeError: Cannot read property 'start' of null in pure_component.js

Here's the error:

TypeError: Cannot read property 'start' of null
    at reportSkipped (pure-component.js:86:28)
    at pure-component.js:97:9
    at Array.filter (native)
    at Collection.filter (/Users/ritz078/.npm-packages/lib/node_modules/jscodeshift/dist/Collection.js:60:46)
    at module.exports (pure-component.js:94:6)

react-codemod/transforms/class.js has a issues

I'm just here to say thanks for this! I'm really amazed at how well it works and I was pleasantly surprised that it doesn't just force an import of create-react-class but it will actually codemod to ES6 class (with public class fields) if it's not using mixins πŸŽ‰ thanks!

Results: 
0 errors
495 unmodified
0 skipped
196 ok

Class transform fails for files with non-ASCII chars in template literals

Transforming a file with a template literal that contains a non-ASCII character will not work.

Any two-byte character seems to bump rightBackTickPos (determined by node.loc.end) 1 higher than what this assert in recast's util.fixTemplateLiteral expects.

The parser seems to count the position of multibyte chars several times in a way that recast doesn't handle properly. At first sight the parser chosen by jscodeshift seems to be babel-core.

Example of a file that won't be transformed:

import React from 'react';

const Foo = React.createClass({
  render() {
    return <div>{`æøΓ₯ß`}</div>;
  },
});

export default Foo;

Output:

$ jscodeshift -t react-codemod/transforms/class.js ../Foo.js 
Processing 1 files... 
Spawning 1 workers...
Sending 1 files to free worker...
 ERR ../Foo.js Transformation error
AssertionError: 'd' === '`'
    at fixTemplateLiteral (/home/misund/.nvm/versions/node/v7.9.0/lib/node_modules/jscodeshift/node_modules/recast/lib/util.js:257:10)
    at Object.util.fixFaultyLocations (/home/misund/.nvm/versions/node/v7.9.0/lib/node_modules/jscodeshift/node_modules/recast/lib/util.js:167:5)
    at TreeCopier.TCp.copy (/home/misund/.nvm/versions/node/v7.9.0/lib/node_modules/jscodeshift/node_modules/recast/lib/parser.js:108:8)
    at TreeCopier.TCp.copy (/home/misund/.nvm/versions/node/v7.9.0/lib/node_modules/jscodeshift/node_modules/recast/lib/parser.js:151:24)
    at Array.map (native)
    at TreeCopier.TCp.copy (/home/misund/.nvm/versions/node/v7.9.0/lib/node_modules/jscodeshift/node_modules/recast/lib/parser.js:101:17)
    at TreeCopier.TCp.copy (/home/misund/.nvm/versions/node/v7.9.0/lib/node_modules/jscodeshift/node_modules/recast/lib/parser.js:151:24)
    at TreeCopier.TCp.copy (/home/misund/.nvm/versions/node/v7.9.0/lib/node_modules/jscodeshift/node_modules/recast/lib/parser.js:151:24)
    at Array.map (native)
    at TreeCopier.TCp.copy (/home/misund/.nvm/versions/node/v7.9.0/lib/node_modules/jscodeshift/node_modules/recast/lib/parser.js:101:17)
All done. 
Results: 
1 errors
0 unmodified
0 skipped
0 ok
Time elapsed: 1.376seconds 

I'm probably not going to bother to look any more at this, especially if I'm the only one having this issue.

If you're reading this in search for a quick and dirty fix, you can try to comment out the assert in recast and hope for the best. (That worked out just fine for me, but your milage may vary.)

Fix tests

Right now they don't pass. Looks like trailing commas are getting added by the printer.

Class mod breaks on arrow function getInitialState

Hi!

So I ran into an issue where running the mod when getInitialState is an arrow
function it breaks (code has been changed due to corporate IP...):

export default React.createClass({
  displayName: 'MyComponent',

  getInitialState: () => ({
    stateThingOne: 'beep',
    stateThingTwo: 'boop'
  }),

  // ...
})

The error message would be this:

TypeError: Cannot read property 'map' of undefined
    at inlineGetInitialState (class.js:294:12)
    at createConstructor (class.js:343:15)
    at createESClass (class.js:362:11)
    at updateToClass (class.js:477:7)
    at NodePath.<anonymous> (class.js:507:31)
    at __paths.forEach (/Users/ricard.sole/.nvm/versions/node/v6.2.2/lib/node_modules/jscodeshift/dist/Collection.js:71:36)
    at Array.forEach (native)
    at Collection.forEach (/Users/ricard.sole/.nvm/versions/node/v6.2.2/lib/node_modules/jscodeshift/dist/Collection.js:70:18)
    at apply (class.js:507:10)
    at module.exports (class.js:514:7)

react-to-react-dom does not work with es6 import

Files are simply skipped due this code:

        root
            .find(j.CallExpression)
            .filter(p => isRequire(p, coreModuleName))

In order to workaround es6 imports there should be something like:

        root
            .find(j.ImportDeclaration)

I'm dumb in AST, so I can't make a PR.

pure-render-mixin transformation error

Getting error:

ERR  ./app/node_modules/components/tweet/index.jsx Transformation error
TypeError: Cannot read property 'get' of undefined
    at Collection.get (/Users/eschaefer/.nvm/versions/node/v4.2.1/lib/node_modules/jscodeshift/dist/Collection.js:205:18)
    at deletePureRenderMixin (/Users/eschaefer/Projects/react-codemod/transforms/pure-render-mixin.js:159:54)
    at removePureRenderMixin (/Users/eschaefer/Projects/react-codemod/transforms/pure-render-mixin.js:180:7)

when running the pure-render-mixin.js on example component:

import React from 'react';
import TranslationsMixin from 'mixins/translations';

var Tweet = React.createClass({

  mixins: [TranslationsMixin],

  render() {

    return (
      <div>
        Stuff
      </div>
    );
  }
});

export default Tweet;

I have tried passing the --mixin-name=TranslationsMixin flag, but no luck. Any idea what could be the issue?

Destructured parameters throws error in PropTypes transform

Hey there!

So our codebase has a component like this

import React, { PropTypes } from 'react';
import classnames from 'classnames';

const propTypes = {
  children: PropTypes.node,
  className: PropTypes.string,
};

const Accordion = ({ children, className, ...other }) => {
  const classNames = classnames('bx--accordion', className);
  return (
    <ul className={classNames} {...other}>
      {children}
    </ul>
  );
};

Accordion.propTypes = propTypes;

export default Accordion;

The codemod currently breaks on the destructured parameter - if I swap it over to

const Accordion = props => {
  const { children, className, ...other } = props;

  const classNames = classnames('bx--accordion', className);
  return (
    <ul className={classNames} {...other}>
      {children}
    </ul>
  );
};

The codemod runs perfectly fine and outputs as expected.

The error is below

 ERR components/Accordion.js Transformation error
TypeError: Cannot read property 'name' of undefined
    at /Users/chrisdhanaraj/bluemix/react-codemod/transforms/React-PropTypes-to-prop-types.js:103:7
    at Array.filter (native)
    at Collection.filter (/Users/chrisdhanaraj/.config/yarn/global/node_modules/jscodeshift/dist/Collection.js:65:46)
    at removeDestructuredPropTypeStatements (/Users/chrisdhanaraj/bluemix/react-codemod/transforms/React-PropTypes-to-prop-types.js:102:6)
    at module.exports (/Users/chrisdhanaraj/bluemix/react-codemod/transforms/React-PropTypes-to-prop-types.js:175:22)

Destructuring for pure-component

Would anyone be interested in an option for the pure-component transform that would destructure the props where possible - i.e. when there's no {...this.props} or doStuff(this.props) and only keys of this.props are used?
I would be down to open a PR if so.

So

render() {
  const { prop1 } = this.props;
  return <div prop1={prop1} prop2={this.props.prop2} />;
}

Would become

({ prop1, prop2 }) => <div prop1={prop1} prop2={prop2} />;

Add support for ES6 classes in sort-comp

In a comment in sort-comp, I noticed the following comment:

NOTE: only works on React.createClass() syntax, not ES6 class.

It would be really lovely if this worked with ES6 classes. 😺

Don't skip files conversion because of mixins?

I want to leave mixins and use them with a 3rd party lib.
When i try to convert components that have mixins in them they get skipped, can i somehow ignore that and still convert components to classes?

create-element-to-jsx doesn't preserve comments

It looks like the create-element-to-jsx transform silently throws away comments within React.createElement calls. Ideally, it should find some way to preserve the comments, or maybe give an error so I can fix those files manually, but if that's too hard or out of scope, I think the behavior should at least be documented.

For example, if you run it on this file:

import React from 'react';

const render = () => {
  return React.createElement('div', {
    className: 'foo',  // This is an important comment.
  });
};

It produces this:

import React from 'react';

const render = () => {
  return <div className="foo" />;
};

React-PropTypes-to-prop-types.js has a transformation error

When trying to upgrade to the latest version of React (migrating prop types and create class stuff), I found a LOT of errors with this particular codemod when running it on my codebase:

~/Developer/paypal/p2pnodeweb (pr/upgrade-react)
πŸš€  $ jscodeshift -t react-codemod/transforms/React-PropTypes-to-prop-types.js public/js/
Processing 691 files... 
Spawning 7 workers...
Sending 50 files to free worker...
Sending 50 files to free worker...
Sending 50 files to free worker...
Sending 50 files to free worker...
Sending 50 files to free worker...
Sending 50 files to free worker...
Sending 50 files to free worker...

...

 ERR public/js/calculator/containers/to-country/__tests__/skip-to-xoom.js Transformation error
TypeError: Cannot read property 'name' of undefined
    at /Users/kdodds/Developer/paypal/p2pnodeweb/react-codemod/transforms/React-PropTypes-to-prop-types.js:91:7
    at Array.filter (native)
    at Collection.filter (/Users/kdodds/.nvm/versions/node/v4.7.0/lib/node_modules/jscodeshift/dist/Collection.js:65:46)
    at removeDestructuredPropTypeStatements (/Users/kdodds/Developer/paypal/p2pnodeweb/react-codemod/transforms/React-PropTypes-to-prop-types.js:90:6)
    at module.exports (/Users/kdodds/Developer/paypal/p2pnodeweb/react-codemod/transforms/React-PropTypes-to-prop-types.js:163:22)

...

All done. 
Results: 
168 errors
0 unmodified
436 skipped
87 ok

Here's what that __tests__/skip-to-xoom.js file looks like:

import React from 'react'
import { render } from 'enzyme'
import SkipToXoom from '../skip-to-xoom'

test('the rendered button redirects to the proper URL when clicked', () => {
	const toCountryData = { countryName: 'India', countryCode: 'IN' }
	const div = renderToDiv({ toCountryData, userLang: 'en_us' })
	const { attribs: { href } } = div.find('a')[0]
	expect(href).toBe('#')
})

/**
 * Render the <SkipToXoom /> component to a div with the given props
 * We have to do some fancy footwork with the Router component to get
 * the Link component in our SkipToXoom component to render out the href
 * @param {Object} props - the props to apply to the component
 * @returns {Element} - the div that contains the element
 */
function renderToDiv(props = {}) {
	return render(<SkipToXoom {...props} dispatch={() => {}} userLang="en" />)
}

Any ideas?

Publish current version to NPM?

The current version on NPM is 2.0.0 and the repo is at 4.0.0. Can we publish the current version? I want to use the sort-comp transform without having to clone and build the repo.

class transform is broken

From the most recent travis-ci build:

...
     [{kind: method, key: [object Object], value: [object Object], static: false, loc: null, type: MethodDefinition, comments: undefined, computed: false, decorators: null}] does not match field "body": [ClassMethod | ClassProperty] of type ClassBody
      
      at add (node_modules/jscodeshift/node_modules/recast/node_modules/ast-types/lib/types.js:580:31)
      at node_modules/jscodeshift/node_modules/recast/node_modules/ast-types/lib/types.js:593:21
      at Array.forEach (native)
      at Function.Object.defineProperty.value [as classBody] (node_modules/jscodeshift/node_modules/recast/node_modules/ast-types/lib/types.js:592:34)
      at createESClass (transforms/class.js:957:7)
      at NodePath.updateToClass (transforms/class.js:1068:5)
      at node_modules/jscodeshift/dist/Collection.js:76:36
      at Array.forEach (native)
      at Collection.forEach (node_modules/jscodeshift/dist/Collection.js:75:18)
      at apply (transforms/class.js:1137:264)
...

I saw the same failures when running npm install locally.

Looking at the build history it appears that 84ef7b7 is good but 5093980 even though the latter didn't introduce any changes into class.js.

I thought maybe it was an issue with the version of jscodeshift I had so I installed 0.3.28 which is what the last passing build installed. That did not fix the situation so I'm guessing it's some other dependency (or sub-dependency) that's causing the issue.

Create JSX - file skipped with no explanation

Hi, I'm playing with this for this first time. My test file is being skipped, and nothing is being logged as to why.

jscodeshift -t react-codemod/transforms/create-element-to-jsx.js -p --dry --run-in-band -v 2 output.js 
Processing 1 files...
Running in dry mode, no files will be written!
 SKIP output.js
All done.
Results: 0 errors 0 unmodified 1 skipped 0 ok
Time elapsed: 0.999 seconds

Is there any way I can get more output from it?

ReactUtils can't detect the component if it extends different component extending React.Component

Let's take this scenario into consideration:

(...)
class AwesomeComponent extends React.Component {
(...)
}

(...)
class Test extends AwesomeComponent {
(...)
}

When using e.g. sort-comp it skips components extending other component extending React.Component.

My temporary fix was changing:

  // Finds all classes that extend React.Component
  const findReactES6ClassDeclaration = path => {
    const componentImport = findReactComponentName(path);
    const selector = componentImport
      ? {
        superClass: {
          type: 'Identifier',
          name: componentImport,
        },
      }
      : {
        superClass: {
          type: 'MemberExpression',
          object: {
            type: 'Identifier',
            name: 'React',
          },
          property: {
            type: 'Identifier',
            name: 'Component',
          },
        },
      };

    return path
     .find(j.ClassDeclaration, selector);
  };

to

  // Finds all classes that extend React.Component
  const findReactES6ClassDeclaration = path => {
    const componentImport = findReactComponentName(path);
    const selector = componentImport
      ? {
        superClass: {
          type: 'Identifier',
          name: componentImport,
        },
      }
      : {
        superClass: {
          type: 'Identifier',
          name: 'AwesomeComponent',
        },
      };

    return path
     .find(j.ClassDeclaration, selector);
  };

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.