This repository contains a collection of codemod scripts based for use with JSCodeshift that help update React APIs.
- npm install -g jscodeshift
- git clone https://github.com/reactjs/react-codemod.gitor download a zip file from- https://github.com/reactjs/react-codemod/archive/master.zip
- Run npm installin the react-codemod directory- Alternatively, run yarnto install in the react-codemod directory for a reliable dependency resolution
 
- Alternatively, run 
- jscodeshift -t <codemod-script> <path>
- Use the -doption for a dry-run and use-pto print the output for comparison
Converts calls to React.createElement into JSX elements.
jscodeshift -t react-codemod/transforms/create-element-to-jsx.js <path>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.
jscodeshift -t react-codemod/transforms/findDOMNode.js <path>Converts manual function bindings in a class (e.g., this.f = this.f.bind(this)) to arrow property initializer functions (e.g., f = () => {}).
jscodeshift -t react-codemod/transforms/manual-bind-to-arrow.js <path>jscodeshift -t react-codemod/transforms/pure-component.js <path>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
jscodeshift -t react-codemod/transforms/pure-render-mixin.js <path>- If --mixin-name=<name>is specified it will look for the specified name instead ofPureRenderMixin. Note that it is not possible to use a namespaced name for the mixin.mixins: [React.addons.PureRenderMixin]will not currently work.
Replaces React.PropTypes references with prop-types and adds the appropriate import or require statement. This codemod is intended for React 15.5+.
jscodeshift -t react-codemod/transforms/React-PropTypes-to-prop-types.js <path>- In addition to running the above codemod you will also need to install the 'prop-types' NPM package.
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.
jscodeshift -t react-codemod/transforms/react-to-react-dom.js <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.
Replaces View.propTypes references with ViewPropTypes and adds the appropriate import or require statement. This codemod is intended for ReactNative 44+.
jscodeshift -t react-codemod/transforms/ReactNative-View-propTypes.js <path>Reorders React component methods to match the ESLint react/sort-comp rule. (Defaults to ordering of the Airbnb style guide.
jscodeshift -t react-codemod/transforms/sort-comp.js <path>- Determine if mixins are convertible. We only transform a createClasscall to an ES6 class component when:
- There are no mixins on the class, or
- options['pure-component']is true, the- mixinsproperty is an array and it only contains pure render mixin (the specific module name can be specified using- options['mixin-module-name'], which defaults to- react-addons-pure-render-mixin)
- Ignore components that:
- Call deprecated APIs. This is very defensive, if the script finds any identifiers called isMounted,getDOMNode,replaceProps,replaceStateorsetPropsit will skip the component
- Explicitly call this.getInitialState()and/orthis.getDefaultProps()since an ES6 class component will no longer have these methods
- Use argumentsin methods since arrow functions don't havearguments. Also please notice thatargumentsshould be very carefully used and it's generally better to switch to spread (...args) instead
- Have inconvertible getInitialState(). Specifically if you have variable declarations likevar props = ...and the right hand side is notthis.propsthen we can't inline the state initialization in theconstructordue to variable shadowing issues
- Have non-primitive right hand side values (like foo: getStuff()) in the class spec
- Transform it to an ES6 class component
- Replace var A = React.createClass(spec)withclass A extends React.Component {spec}. If a component uses pure render mixin and passes the mixins test (as described above), it will extendReact.PureComponentinstead - Remove therequire/importstatement that imports pure render mixin when it's no longer being referenced
- Pull out all statics defined on staticsplus the few special cased statics likechildContextTypes,contextTypes,displayName,getDefaultProps(), andpropTypesand transform them tostaticproperties (static propTypes = {...};) - IfgetDefaultProps()is simple (i.e. it only contains a return statement that returns something) it will be converted to a simple assignment (static defaultProps = ...;). Otherwise an IIFE (immediately-invoked function expression) will be created (static defaultProps = function() { ... }();). Note that this means that the function will be executed only a single time per app-lifetime. In practice this hasn't caused any issues —getDefaultPropsshould not contain any side-effects
- Transform getInitialState()- If there's nogetInitialState()or thegetInitialState()function is simple (i.e., it only contains a return statement that returns something) then we don't need a constructor;statewill be lifted to a property initializer (state = ...;)- However, if the RHS of returncontains references tothisother thanthis.propsand/orthis.context, we can't be sure about what you'll need fromthis. We need to ensure that our property initializers' evaluation order is safe, so we deferstate's initialization by moving it all the way down until all other property initializers have been initialized - IfgetInitialState()is not simple, we create aconstructorand convertgetInitialState()to an assignment tothis.state
- constructoralways have- propsas the first parameter
- We only put contextas the second parameter when (one of) the following things happen ingetInitialState():- It accesses this.context, or
- There's a direct method call this.x(), or
- thisis referenced alone
 
- It accesses 
- Rewrite accesses to this.propstopropsand accesses tothis.contexttocontextsince the values will be passed asconstructorarguments- Remove simple variable declarations like var props = this.props;andvar context = this.context
 
- Remove simple variable declarations like 
- Rewrite top-level return statements (return {...};) tothis.state = {...}- Add return;after the assignment when the return statement is part of a control flow statement (not a direct child ofgetInitialState()'s body) and not in an inner function declaration
 
- Add 
 
- However, if the RHS of 
- Transform all non-lifecycle methods and fields to class property initializers (like onClick = () => {};). All your Flow annotations will be preserved - It's actually not necessary to transform all methods to arrow functions (i.e., to bind them), but this behavior is the same ascreateClass()and we can make sure that we won't accidentally break stuff
- Generate Flow annotations from propTypesand put it on the class (this only happens when there's/* @flow */in your code andoptions['flow']istrue)
- Flow actually understands propTypesincreateClasscalls but not ES6 class components. Here the transformation logic is identical to how Flow treatspropTypes
- Notice that Flow treats an optional propType as non-nullable
- For example, foo: React.PropTypes.numberis valid when you pass{},{foo: null}, or{foo: undefined}as props at runtime. However, when Flow infers type from acreateClasscall, only{}and{foo: undefined}are valid;{foo: null}is not. Thus the equivalent type annotation in Flow is actually{foo?: number}. The question mark on the left hand side indicates{}and{foo: undefined}are fine, but whenfoois present it must be anumber
 
- For example, 
- For propTypesfields that can't be recognized by Flow,$FlowFixMewill be used
- React.createClassis no longer present in React 16. So, if a- createClasscall cannot be converted to a plain class, the script will fallback to using the- create-react-classpackage.
- Replaces React.createClasswithReactCreateClass.
- Adds a requireorimportstatement forcreate-react-class. The import style is inferred from the import style of thereactimport. The default module name can be overridden with the--create-class-module-nameoption.
- Prunes the reactimport if there are no more references to it.
jscodeshift -t ./transforms/class.js --mixin-module-name=react-addons-pure-render-mixin --flow=true --pure-component=true --remove-runtime-proptypes=false <path>Options to recast's printer can be provided
through the printOptions command line argument
jscodeshift -t transform.js <path> --printOptions='{"quote":"double"}'The scripts in this repository are provided in the hope that they are useful, but they are not officially maintained, and we generally will not fix community-reported issues. They are a collection of scripts that were previously used internally within Facebook or were contributed by the community, and we rely on community contributions to fix any issues discovered or make any improvements. If you want to contribute, you're welcome to submit a pull request.