Skip to content

Commit

Permalink
[New] : Enforce no unused React elements
Browse files Browse the repository at this point in the history
  • Loading branch information
duncanbeevers committed Jan 14, 2021
1 parent 0e9a193 commit a20dea1
Show file tree
Hide file tree
Showing 5 changed files with 144 additions and 1 deletion.
3 changes: 2 additions & 1 deletion README.md
Expand Up @@ -132,6 +132,7 @@ Enable the rules that you would like to use.
* [react/no-unescaped-entities](docs/rules/no-unescaped-entities.md): Detect unescaped HTML entities, which might represent malformed tags
* [react/no-unknown-property](docs/rules/no-unknown-property.md): Prevent usage of unknown DOM property (fixable)
* [react/no-unsafe](docs/rules/no-unsafe.md): Prevent usage of unsafe lifecycle methods
* [react/no-unused-elements](docs/rules/no-unused-elements.md): Disallow unused React elements
* [react/no-unused-prop-types](docs/rules/no-unused-prop-types.md): Prevent definitions of unused prop types
* [react/no-unused-state](docs/rules/no-unused-state.md): Prevent definition of unused state fields
* [react/no-will-update-set-state](docs/rules/no-will-update-set-state.md): Prevent usage of setState in componentWillUpdate
Expand Down Expand Up @@ -179,7 +180,7 @@ Enable the rules that you would like to use.
* [react/jsx-no-duplicate-props](docs/rules/jsx-no-duplicate-props.md): Enforce no duplicate props
* [react/jsx-no-literals](docs/rules/jsx-no-literals.md): Prevent using string literals in React component definition
* [react/jsx-no-script-url](docs/rules/jsx-no-script-url.md): Forbid `javascript:` URLs
* [react/jsx-no-target-blank](docs/rules/jsx-no-target-blank.md): Forbid `target="_blank"` attribute without `rel="noreferrer"`
* [react/jsx-no-target-blank](docs/rules/jsx-no-target-blank.md): Forbid `target="_blank"` attribute without `rel="noreferrer"` (fixable)
* [react/jsx-no-undef](docs/rules/jsx-no-undef.md): Disallow undeclared variables in JSX
* [react/jsx-no-useless-fragment](docs/rules/jsx-no-useless-fragment.md): Disallow unnecessary fragments (fixable)
* [react/jsx-one-expression-per-line](docs/rules/jsx-one-expression-per-line.md): Limit to one expression per line in JSX (fixable)
Expand Down
25 changes: 25 additions & 0 deletions docs/rules/no-unused-elements.md
@@ -0,0 +1,25 @@
# Disallow unused React elements (react/no-unused-elements)

An unused React element indicates a logic error.

## Rule Details

Examples of **incorrect** code for this rule:

```jsx
<div />;
```

```js
React.createElement('div');
```

Examples of **correct** code for this rule:

```js
return <div />;
```

```js
const partial = <div />;
```
1 change: 1 addition & 0 deletions index.js
Expand Up @@ -76,6 +76,7 @@ const allRules = {
'no-unescaped-entities': require('./lib/rules/no-unescaped-entities'),
'no-unknown-property': require('./lib/rules/no-unknown-property'),
'no-unsafe': require('./lib/rules/no-unsafe'),
'no-unused-elements': require('./lib/rules/no-unused-elements'),
'no-unused-prop-types': require('./lib/rules/no-unused-prop-types'),
'no-unused-state': require('./lib/rules/no-unused-state'),
'no-will-update-set-state': require('./lib/rules/no-will-update-set-state'),
Expand Down
53 changes: 53 additions & 0 deletions lib/rules/no-unused-elements.js
@@ -0,0 +1,53 @@
/**
* @fileoverview Disallow unused React elements
* @author Duncan Beevers
*/

'use strict';

const Components = require('../util/Components');
const docsUrl = require('../util/docsUrl');

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

const NO_UNUSED_ELEMENTS_MESSAGE = 'noUnusedElements';

module.exports = {
meta: {
docs: {
description: 'Disallow unused React elements',
category: 'Best Practices',
recommended: false,
url: docsUrl('no-unused-elements')
},
messages: {
[NO_UNUSED_ELEMENTS_MESSAGE]: 'Unused React element'
},
schema: [{
type: 'object',
additionalProperties: false
}]
},

create: Components.detect((context, components, utils) => ({
JSXElement(node) {
if (node.parent.type === 'ExpressionStatement') {
context.report({
node,
messageId: NO_UNUSED_ELEMENTS_MESSAGE
});
}
},
CallExpression(node) {
if (utils.isCreateElement(node) && node.parent.type === 'ExpressionStatement') {
context.report({
node,
messageId: NO_UNUSED_ELEMENTS_MESSAGE
});
}
}
})
)
};
63 changes: 63 additions & 0 deletions tests/lib/rules/no-unused-elements.js
@@ -0,0 +1,63 @@
/**
* @fileoverview Disallow unused React elements
* @author Duncan Beevers
*/

'use strict';

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

const RuleTester = require('eslint').RuleTester;
const rule = require('../../../lib/rules/no-unused-elements');

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

const ruleTester = new RuleTester({
parserOptions: {
ecmaVersion: 2018,
sourceType: 'module',
ecmaFeatures: {
jsx: true
}
}
});

const tests = {
valid: [
{
code: 'const partial = <div />'
},
{
code: '() => <div />'
},
{
code: 'const partial = React.createElement(\'div\', {}, \'\')'
}
],
invalid: [
{
code: '<div />',
errors: [{
message: 'Unused React element'
}]
},
{
code: 'React.createElement(\'div\', {}, \'\')',
errors: [{
message: 'Unused React element'
}]
},
{
code: 'if (condition) { <div /> }',
errors: [{
message: 'Unused React element'
}]
}
]
};

ruleTester.run('no-unused-elements', rule, tests);

0 comments on commit a20dea1

Please sign in to comment.