Skip to content

Commit d2480bc

Browse files
committed
Merge pull request #5 from glenjamin/react-in-jsx-scope
Add react-in-jsx-scope rule
2 parents 9c43de0 + 5fec402 commit d2480bc

File tree

4 files changed

+112
-2
lines changed

4 files changed

+112
-2
lines changed

docs/rules/react-in-jsx-scope.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Prevent errors from not requiring React when using JSX (react-in-jsx-scope)
2+
3+
When using JSX, `<a />` expands to `React.createElement("a")`. Therefore the
4+
`React` variable must be in scope.
5+
6+
## Rule Details
7+
8+
The following patterns are considered warnings:
9+
10+
```js
11+
var Hello = <div>Hello {this.props.name}</div>;
12+
```
13+
14+
The following patterns are not considered warnings:
15+
16+
```js
17+
var React = require('react'); // or equivalent import
18+
var Hello = <div>Hello {this.props.name}</div>;
19+
```
20+
21+
## When Not To Use It
22+
23+
If you are setting `React` as a global variable, you will not need this rule.

index.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ module.exports = {
88
'wrap-multilines': require('./lib/rules/wrap-multilines'),
99
'self-closing-comp': require('./lib/rules/self-closing-comp'),
1010
'no-did-mount-set-state': require('./lib/rules/no-did-mount-set-state'),
11-
'no-did-update-set-state': require('./lib/rules/no-did-update-set-state')
11+
'no-did-update-set-state': require('./lib/rules/no-did-update-set-state'),
12+
'react-in-jsx-scope': require('./lib/rules/react-in-jsx-scope')
1213
},
1314
rulesConfig: {
1415
'no-multi-comp': 0,
@@ -17,6 +18,7 @@ module.exports = {
1718
'wrap-multilines': 0,
1819
'self-closing-comp': 0,
1920
'no-did-mount-set-state': 0,
20-
'no-did-update-set-state': 0
21+
'no-did-update-set-state': 0,
22+
'react-in-jsx-scope': 0
2123
}
2224
};

lib/rules/react-in-jsx-scope.js

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/**
2+
* @fileoverview Validate that React is in scope when using JSX.
3+
* @author Glen Mailer
4+
*/
5+
"use strict";
6+
7+
// -----------------------------------------------------------------------------
8+
// Rule Definition
9+
// -----------------------------------------------------------------------------
10+
11+
module.exports = function(context) {
12+
13+
var NOT_DEFINED_MESSAGE = "'React' must be in scope when using JSX";
14+
15+
function findVariable(variables, name) {
16+
var i, len;
17+
for (i = 0, len = variables.length; i < len; i++) {
18+
if (variables[i].name === name) {
19+
return true;
20+
}
21+
}
22+
return false;
23+
}
24+
25+
function variablesInScope() {
26+
var scope = context.getScope(),
27+
variables = scope.variables;
28+
29+
while (scope.type !== "global") {
30+
scope = scope.upper;
31+
variables = scope.variables.concat(variables);
32+
}
33+
34+
return variables;
35+
}
36+
37+
return {
38+
39+
"JSXOpeningElement": function(node) {
40+
var variables = variablesInScope();
41+
if (!findVariable(variables, 'React')) {
42+
context.report(node, NOT_DEFINED_MESSAGE);
43+
}
44+
}
45+
46+
};
47+
48+
};

tests/lib/rules/react-in-jsx-scope.js

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/**
2+
* @fileoverview Tests for react-in-jsx-scope
3+
* @author Glen Mailer
4+
*/
5+
6+
"use strict";
7+
8+
// -----------------------------------------------------------------------------
9+
// Requirements
10+
// -----------------------------------------------------------------------------
11+
12+
var eslint = require('eslint').linter;
13+
var ESLintTester = require('eslint-tester');
14+
15+
// -----------------------------------------------------------------------------
16+
// Tests
17+
// -----------------------------------------------------------------------------
18+
19+
var eslintTester = new ESLintTester(eslint);
20+
eslintTester.addRuleTest("lib/rules/react-in-jsx-scope", {
21+
valid: [
22+
{code: "var React, App; <App />;", args: [1, {vars: "all"}], ecmaFeatures: {jsx: true}},
23+
{code: "var React; <img />;", args: [1, {vars: "all"}], ecmaFeatures: {jsx: true}},
24+
{code: "var React; <x-gif />;", args: [1, {vars: "all"}], ecmaFeatures: {jsx: true}},
25+
{code: "var React, App, a=1; <App attr={a} />;", ecmaFeatures: {jsx: true}},
26+
{code: "var React, App, a=1; function elem() { return <App attr={a} />; }",
27+
ecmaFeatures: {jsx: true}}
28+
],
29+
invalid: [
30+
{code: "var App, a = <App />;",
31+
errors: [{message: "'React' must be in scope when using JSX"}], ecmaFeatures: {jsx: true}},
32+
{code: "var a = <App />;",
33+
errors: [{message: "'React' must be in scope when using JSX"}], ecmaFeatures: {jsx: true}},
34+
{code: "var a = <img />;",
35+
errors: [{message: "'React' must be in scope when using JSX"}], ecmaFeatures: {jsx: true}}
36+
]
37+
});

0 commit comments

Comments
 (0)