-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add no-find-dom-node rule (fixes #678)
- Loading branch information
Showing
5 changed files
with
185 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
# Prevent usage of findDOMNode (no-find-dom-node) | ||
|
||
Facebook will eventually deprecate `findDOMNode` as it blocks certain improvements in React in the future. | ||
|
||
It is recommended to use callback refs instead. See [Dan Abramov comments and examples](https://github.com/yannickcr/eslint-plugin-react/issues/678#issue-165177220). | ||
|
||
## Rule Details | ||
|
||
The following patterns are considered warnings: | ||
|
||
```js | ||
class MyComponent extends Component { | ||
componentDidMount() { | ||
findDOMNode(this).scrollIntoView(); | ||
} | ||
render() { | ||
return <div /> | ||
} | ||
} | ||
``` | ||
|
||
The following patterns are not considered warnings: | ||
|
||
```js | ||
class MyComponent extends Component { | ||
componentDidMount() { | ||
this.node.scrollIntoView(); | ||
} | ||
render() { | ||
return <div ref={node => this.node = node} /> | ||
} | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
/** | ||
* @fileoverview Prevent usage of findDOMNode | ||
* @author Yannick Croissant | ||
*/ | ||
'use strict'; | ||
|
||
// ------------------------------------------------------------------------------ | ||
// Rule Definition | ||
// ------------------------------------------------------------------------------ | ||
|
||
module.exports = function(context) { | ||
|
||
// -------------------------------------------------------------------------- | ||
// Public | ||
// -------------------------------------------------------------------------- | ||
|
||
return { | ||
|
||
CallExpression: function(node) { | ||
var callee = node.callee; | ||
if ( | ||
callee.type !== 'MemberExpression' || ( | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
yannickcr
Author
Member
|
||
callee.object.callee && callee.object.callee.name !== 'findDOMNode' && | ||
callee.property.name !== 'findDOMNode' | ||
) | ||
) { | ||
return; | ||
} | ||
var ancestors = context.getAncestors(callee); | ||
for (var i = 0, j = ancestors.length; i < j; i++) { | ||
if (ancestors[i].type === 'Property' || ancestors[i].type === 'MethodDefinition') { | ||
context.report({ | ||
node: callee, | ||
message: 'Do not use findDOMNode' | ||
}); | ||
break; | ||
} | ||
} | ||
} | ||
}; | ||
|
||
}; | ||
|
||
module.exports.schema = []; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
/** | ||
* @fileoverview Prevent usage of findDOMNode | ||
* @author Yannick Croissant | ||
*/ | ||
'use strict'; | ||
|
||
// ------------------------------------------------------------------------------ | ||
// Requirements | ||
// ------------------------------------------------------------------------------ | ||
|
||
var rule = require('../../../lib/rules/no-find-dom-node'); | ||
var RuleTester = require('eslint').RuleTester; | ||
|
||
var parserOptions = { | ||
ecmaVersion: 6, | ||
ecmaFeatures: { | ||
jsx: true | ||
} | ||
}; | ||
|
||
// ------------------------------------------------------------------------------ | ||
// Tests | ||
// ------------------------------------------------------------------------------ | ||
|
||
var ruleTester = new RuleTester(); | ||
ruleTester.run('no-find-dom-node', rule, { | ||
|
||
valid: [{ | ||
code: [ | ||
'var Hello = function() {};' | ||
].join('\n'), | ||
parserOptions: parserOptions | ||
}, { | ||
code: [ | ||
'var Hello = React.createClass({', | ||
' render: function() {', | ||
' return <div>Hello</div>;', | ||
' }', | ||
'});' | ||
].join('\n'), | ||
parserOptions: parserOptions | ||
}, { | ||
code: [ | ||
'var Hello = React.createClass({', | ||
' componentDidMount: function() {', | ||
' someNonMemberFunction(arg);', | ||
' this.someFunc = React.findDOMNode;', | ||
' },', | ||
' render: function() {', | ||
' return <div>Hello</div>;', | ||
' }', | ||
'});' | ||
].join('\n'), | ||
parserOptions: parserOptions | ||
}], | ||
|
||
invalid: [{ | ||
code: [ | ||
'var Hello = React.createClass({', | ||
' componentDidMount: function() {', | ||
' React.findDOMNode(this).scrollIntoView();', | ||
' },', | ||
' render: function() {', | ||
' return <div>Hello</div>;', | ||
' }', | ||
'});' | ||
].join('\n'), | ||
parserOptions: parserOptions, | ||
errors: [{ | ||
message: 'Do not use findDOMNode' | ||
}] | ||
}, { | ||
code: [ | ||
'var Hello = React.createClass({', | ||
' componentDidMount: function() {', | ||
' ReactDOM.findDOMNode(this).scrollIntoView();', | ||
' },', | ||
' render: function() {', | ||
' return <div>Hello</div>;', | ||
' }', | ||
'});' | ||
].join('\n'), | ||
parserOptions: parserOptions, | ||
errors: [{ | ||
message: 'Do not use findDOMNode' | ||
}] | ||
}, { | ||
code: [ | ||
'class Hello extends Component {', | ||
' componentDidMount() {', | ||
' findDOMNode(this).scrollIntoView();', | ||
' }', | ||
' render() {', | ||
' return <div>Hello</div>;', | ||
' }', | ||
'};' | ||
].join('\n'), | ||
parserOptions: parserOptions, | ||
errors: [{ | ||
message: 'Do not use findDOMNode' | ||
}] | ||
}] | ||
}); |
It looks like this rule can get triggered when
callee.type == 'MemberExpression'
buttext != findDOMNode
. is that correct?when I run the latest eslint on my project I get thousands of incorrect findDOMNode errors (in files where findDOMNode isn't being used at all). this appears to be the cause