As of React 15.5, createClass is deprecated. You’ll get warnings in the console if you’re using it in your code – and, when React 16 comes out, createClass will be removed entirely.
What to do? Well, update your code, of course!
This video and article go over how to convert to ES6 classes. You also might want to know how to convert to stateless function components and I’ve got a video and article for that as well.
Replace createClass
When replacing React.createClass
there are 2 options:
- use an ES6 class
- use a stateless function (learn how here)
Here’s how to decide:
- Use an ES6 class if either:
- the component uses state (search for “this.state” to make sure)
- the component uses lifecycle methods like
componentDidUpdate
,componentDidMount
, etc. - the component has handler methods (
handleClick
and such)
- Use a stateless function if none of the above is true
This post covers converting to ES6 classes – another one covers stateless functions.
Before: createClass
import React from 'react';
var InputControl = React.createClass({
propTypes: {
initialValue: React.PropTypes.string
},
componentDidMount: function() {
console.log('mounted');
},
getDefaultProps: function() {
return {
initialValue: ''
};
}},
getInitialState: function() {
return {
text: this.props.initialValue || 'placeholder'
};
},
handleChange: function(event) {
this.setState({
text: event.target.value
});
},
render: function() {
return (
<div>
Type something:
<input onChange={this.handleChange}
value={this.state.text} />
</div>
);
}
});
After: ES6 Class
import React from 'react';
// PropTypes is a separate package now:
import PropTypes from 'prop-types';
// replace React.createClass with a class:
class InputControl extends React.Component {
// Use static properties for propTypes/defaultProps
static propTypes = {
initialValue: PropTypes.string
}
static defaultProps = {
initialValue: ''
}
// Initialize state right in the class body,
// with a property initializer:
state = {
text: this.props.initialValue || 'placeholder'
}
// Use an arrow function to preserve the "this" binding
// without having to bind in the constructor, or in render.
handleChange = (event) => {
this.setState({
text: event.target.value
});
}
// In classes, functions are written without
// the 'function' keyword. Also, notice there are no commas
// between properties
render() {
return (
<div>
Type something:
<input onChange={this.handleChange}
value={this.state.text} />
</div>
);
}
}
What changed?
- Properties in the class don’t have commas between them, like they do in plain objects.
- Functions are written without the “function” keyword.
- Arrow functions are used for member functions that need to preserve the
this
binding. - State is initialized with an assignment (“property initializer”) rather than having to implement a function to return it.
- PropTypes is no longer under React, so
React.PropTypes
is replaced byPropTypes
. - propTypes and defaultProps are set as static properties instead of functions, though they can still be set outside the class too, like
InputControl.propTypes = { ... }
.
Example Project
I put together an example project with 7 different components, both before and after conversion, including the codemod-generated version.createClass to stateless functions. You can download it here (no email required).
Automate It!
The helpful folks at Facebook created a project called react-codemod which holds a suite of scripts for automatically transforming old-and-busted React code into the modern style.
Right now it contains 11 different scripts to transform all kinds of things, like changing React.PropTypes
to PropTypes
, converting createClass
to ES6 classes, and even sorting the methods in a component to match best practices. You can see the full list in the repo but we’ll go over how to apply the createClass -> ES6 transform here.
Straight from the repo, the instructions are:
npm install -g jscodeshift
(oryarn global add jscodeshift
)git clone https://github.com/reactjs/react-codemod.git
- Run
npm install
(oryarn
) in the react-codemod directory - Run
jscodeshift -t <codemod-script> <path>
- codemod scripts are under
react-codemod/transforms
, and<path>
should point to a file (or multiple files) in your source code.
- codemod scripts are under
The jscodeshift
tool can take the the -d
option for a dry-run (print what would be done, but don’t make changes) and the -p
to print the output for comparison.
Here’s the command to transform createClass to ES6 (it’s long, I know):
jscodeshift -t react-codemod/transforms/class.js --mixin-module-name=react-addons-pure-render-mixin --flow=true --pure-component=true --remove-runtime-proptypes=false <path>
It did a nice job on the test file I passed through it. My results are included with the example project, which you can download here.