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

add rule to prevent deprecated use of React.render, etc. #356

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ Finally, enable all of the rules that you would like to use.
"react/jsx-uses-react": 1,
"react/jsx-uses-vars": 1,
"react/no-danger": 1,
"react/no-deprecated-reactdom": 1,
"react/no-did-mount-set-state": 1,
"react/no-did-update-set-state": 1,
"react/no-direct-mutation-state": 1,
Expand Down Expand Up @@ -105,6 +106,7 @@ Finally, enable all of the rules that you would like to use.
* [jsx-uses-react](docs/rules/jsx-uses-react.md): Prevent React to be incorrectly marked as unused
* [jsx-uses-vars](docs/rules/jsx-uses-vars.md): Prevent variables used in JSX to be incorrectly marked as unused
* [no-danger](docs/rules/no-danger.md): Prevent usage of dangerous JSX properties
* [no-deprecated-reactdom](docs/rules/no-deprecated-reactdom.md): Prevent accessing methods on `React` that have moved to `ReactDOM`
* [no-did-mount-set-state](docs/rules/no-did-mount-set-state.md): Prevent usage of `setState` in `componentDidMount`
* [no-did-update-set-state](docs/rules/no-did-update-set-state.md): Prevent usage of `setState` in `componentDidUpdate`
* [no-direct-mutation-state](docs/rules/no-direct-mutation-state.md): Prevent direct mutation of `this.state`
Expand Down
35 changes: 35 additions & 0 deletions docs/rules/no-deprecated-reactdom.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Prevent usage of ReactDOM methods from React object

In React 0.14, several methods moved from 'react' to the separate 'react-dom' and 'react-dom-server' packages, and accessing these methods via 'react' is now deprecated. This rule warns if the moved methods are accessed on an object called `React`.

## Rule Details

The following patterns are considered warnings:

```js
var root = document.getElementById('root');
React.render(<MyComponent />, root);

React.unmountComponentAtNode(root);

React.findDOMNode(this.refs.foo);

React.renderToString(<MyComponent />);

React.renderToStaticMarkup(<MyComponent />);
```

The following patterns are not considered warnings:

```js
var root = document.getElementById('root');
ReactDOM.render(<MyComponent />, root);

ReactDOM.unmountComponentAtNode(root);

ReactDOM.findDOMNode(this.refs.foo);

ReactDOMServer.renderToString(<MyComponent />);

ReactDOMServer.renderToStaticMarkup(<MyComponent />);
```
2 changes: 2 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ module.exports = {
'no-direct-mutation-state': require('./lib/rules/no-direct-mutation-state'),
'forbid-prop-types': require('./lib/rules/forbid-prop-types'),
'prefer-es6-class': require('./lib/rules/prefer-es6-class'),
'no-deprecated-reactdom': require('./lib/rules/no-deprecated-reactdom'),
'jsx-key': require('./lib/rules/jsx-key')
},
rulesConfig: {
Expand Down Expand Up @@ -69,6 +70,7 @@ module.exports = {
'no-direct-mutation-state': 0,
'forbid-prop-types': 0,
'prefer-es6-class': 0,
'no-deprecated-reactdom': 0,
'jsx-key': 0
}
};
43 changes: 43 additions & 0 deletions lib/rules/no-deprecated-reactdom.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/**
* @fileoverview Don't access ReactDOM/ReactDOMServer methods on React object
* @author Scott Feeney
*/
'use strict';

// ------------------------------------------------------------------------------
// Constants
// ------------------------------------------------------------------------------

var movedMethods = {
render: 'ReactDOM',
unmountComponentAtNode: 'ReactDOM',
findDOMNode: 'ReactDOM',
renderToString: 'ReactDOMServer',
renderToStaticMarkup: 'ReactDOMServer'
};

// ------------------------------------------------------------------------------
// Rule Definition
// ------------------------------------------------------------------------------

module.exports = function(context) {
return {
MemberExpression: function(node) {
if (
node.object.type === 'Identifier'
&& node.object.name.match(/^react$/i)
&& node.property.type === 'Identifier'
&& Object.keys(movedMethods).indexOf(node.property.name) !== -1
) {
var method = node.property.name;
context.report({
node: node,
message: (
'React.' + method + ' is deprecated; ' +
'use ' + movedMethods[method] + '.' + method + ' instead.'
)
});
}
}
};
};
88 changes: 88 additions & 0 deletions tests/lib/rules/no-deprecated-reactdom.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/**
* @fileoverview Don't access ReactDOM/ReactDOMServer methods on React object
* @author Scott Feeney
*/
'use strict';

// ------------------------------------------------------------------------------
// Requirements
// ------------------------------------------------------------------------------

var rule = require('../../../lib/rules/no-deprecated-reactdom');
var RuleTester = require('eslint').RuleTester;

require('babel-eslint');

// ------------------------------------------------------------------------------
// Tests
// ------------------------------------------------------------------------------

var ruleTester = new RuleTester();
ruleTester.run('no-deprecated-reactdom', rule, {

valid: [
'var MyClass = React.createClass({});',
'var element = React.createElement(\'p\', {}, null);',
'var clone = React.cloneElement(element);',
'ReactDOM.render(element, container);',
'ReactDOM.unmountComponentAtNode(container);',
'ReactDOM.findDOMNode(instance);',
'ReactDOMServer.renderToString(element);',
'ReactDOMServer.renderToStaticMarkup(element);'
],

invalid: [
{
code: 'React.render(element, container);',
errors: [
{
message: 'React.render is deprecated; use ReactDOM.render instead.'
}
]
},
{
code: 'React.unmountComponentAtNode(container);',
errors: [
{
message: (
'React.unmountComponentAtNode is deprecated; ' +
'use ReactDOM.unmountComponentAtNode instead.'
)
}
]
},
{
code: 'React.findDOMNode(instance);',
errors: [
{
message: (
'React.findDOMNode is deprecated; ' +
'use ReactDOM.findDOMNode instead.'
)
}
]
},
{
code: 'React.renderToString(element);',
errors: [
{
message: (
'React.renderToString is deprecated; ' +
'use ReactDOMServer.renderToString instead.'
)
}
]
},
{
code: 'React.renderToStaticMarkup(element);',
errors: [
{
message: (
'React.renderToStaticMarkup is deprecated; ' +
'use ReactDOMServer.renderToStaticMarkup instead.'
)
}
]
}
]
});