This repository has been archived by the owner on Jan 3, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
2,625 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
root = true | ||
|
||
[*] | ||
charset = utf-8 | ||
end_of_line = lf | ||
indent_style = space | ||
indent_size = 2 | ||
insert_final_newline = true | ||
trim_trailing_whitespace = true | ||
|
||
[*.md] | ||
trim_trailing_whitespace = false |
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,3 @@ | ||
node_modules | ||
*.tgz | ||
*~ |
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,4 @@ | ||
language: node_js | ||
node_js: | ||
- "9" | ||
- "8" |
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 |
---|---|---|
@@ -1 +1,4 @@ | ||
# eslint-plugin-tipsi | ||
# eslint-plugin-tipsi | ||
|
||
### List or rules | ||
* [tipsi/remove-event-listener](/docs/rules/remove-event-listener.md) |
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,203 @@ | ||
# bind over developer to write removeEventListener if addEventListener exists (remove-event-listener) | ||
|
||
Every `addEventListener` should be paired with `removeEventListener` to avoid memory leaks | ||
|
||
## Rule Details | ||
|
||
This rule binds over developer to write `removeEventListener` if `addEventListener` exists | ||
|
||
### code | ||
|
||
Examples of **incorrect** code for this rule: | ||
|
||
```js | ||
/* eslint tipsi/remove-event-listener: ["error"] */ | ||
|
||
class App { | ||
handleRootNodeClick = () => { | ||
console.log('click') | ||
} | ||
|
||
componentDidMount() { | ||
this.rootNodeRef.addEventListener('click', this.handleRootNodeClick) | ||
} | ||
|
||
render() { | ||
return ( | ||
<div ref={node => this.rootNodeRef = node} /> | ||
) | ||
} | ||
} | ||
``` | ||
You will get next error: | ||
``` | ||
click on this.rootNodeRef does not have a corresponding removeEventListener | ||
``` | ||
|
||
```js | ||
/* eslint tipsi/remove-event-listener: ["error"] */ | ||
|
||
class App { | ||
handleRootNodeClick = () => { | ||
console.log('click') | ||
} | ||
|
||
handleRootNodeKeyPress = () => { | ||
console.log('keyPress') | ||
} | ||
|
||
componentDidMount() { | ||
this.rootNodeRef.addEventListener('click', this.handleRootNodeClick) | ||
} | ||
|
||
componentWillUnmount() { | ||
this.rootNodeRef.removeEventListener('keypress', this.handleRootNodeKeyPress) | ||
} | ||
|
||
render() { | ||
return ( | ||
<div ref={node => this.rootNodeRef = node} /> | ||
) | ||
} | ||
} | ||
``` | ||
You will get next error: | ||
``` | ||
click on this.rootNodeRef does not have a corresponding removeEventListener | ||
``` | ||
|
||
```js | ||
/* eslint tipsi/remove-event-listener: ["error"] */ | ||
|
||
class App { | ||
handleRootNodeClick = () => { | ||
console.log('click') | ||
} | ||
|
||
handleRootNodeKeyPress = () => { | ||
console.log('keyPress') | ||
} | ||
|
||
componentDidMount() { | ||
this.rootNodeRef.addEventListener('click', this.handleRootNodeClick) | ||
} | ||
|
||
componentWillUnmount() { | ||
this.rootNodeRef.removeEventListener('click', this.handleRootNodeKeyPress) | ||
} | ||
|
||
render() { | ||
return ( | ||
<div ref={node => this.rootNodeRef = node} /> | ||
) | ||
} | ||
} | ||
``` | ||
You will get next error: | ||
``` | ||
this.handleRootNodeClick and this.handleRootNodeKeyPress on this.rootNodeRef for click do not match | ||
``` | ||
|
||
```js | ||
/* eslint tipsi/remove-event-listener: ["error"] */ | ||
|
||
class App { | ||
handleRootNodeClick = () => { | ||
console.log('click') | ||
} | ||
|
||
handleRootNodeTap = () => { | ||
console.log('click') | ||
} | ||
|
||
componentDidMount() { | ||
this.rootNodeRef.addEventListener('click', () => { | ||
console.log('click') | ||
}) | ||
|
||
this.rootNodeRef.addEventListener('tap', function () { | ||
console.log('tap') | ||
}) | ||
} | ||
|
||
componentWillUnmount() { | ||
this.rootNodeRef.removeEventListener('click', this.handleRootNodeClick) | ||
this.rootNodeRef.removeEventListener('tap', this.handleRootNodeTap) | ||
} | ||
|
||
render() { | ||
return ( | ||
<div ref={node => this.rootNodeRef = node} /> | ||
) | ||
} | ||
} | ||
``` | ||
You will get next errors: | ||
``` | ||
event handler for click on this.rootNodeRef is arrow function arrow functions are prohibited as event handlers | ||
event handler for tap on this.rootNodeRef is plain function plain functions are prohibited as event handlers | ||
``` | ||
|
||
```js | ||
/* eslint tipsi/remove-event-listener: ["error"] */ | ||
|
||
const clickHandler = () => { | ||
console.log('click') | ||
} | ||
|
||
const anotherClickHandler = () => { | ||
console.log('click') | ||
} | ||
|
||
class App { | ||
componentDidMount() { | ||
this.rootNodeRef.addEventListener('click', clickHandler) | ||
} | ||
|
||
componentWillUnmount() { | ||
this.rootNodeRef.removeEventListener('click', anotherClickHandler) | ||
} | ||
|
||
render() { | ||
return ( | ||
<div ref={node => this.rootNodeRef = node} /> | ||
) | ||
} | ||
} | ||
``` | ||
You will get next error: | ||
``` | ||
clickHandler and anotherClickHandler on this.rootNodeRef for click do not match | ||
``` | ||
|
||
Example of **correct** code for this rule: | ||
|
||
```js | ||
/* eslint tipsi/remove-event-listener: ["error"] */ | ||
|
||
const handleClack = () => { | ||
console.log('click clack') | ||
} | ||
|
||
class App { | ||
handleRootNodeClick = () => { | ||
console.log('click') // eslint-disable-line no-console | ||
} | ||
|
||
componentDidMount() { | ||
this.rootNodeRef.addEventListener('click', this.handleRootNodeClick) | ||
this.rootNodeRef.addEventListener('clack', handleClickClack) | ||
} | ||
|
||
componentWillUnmount() { | ||
this.rootNodeRef.removeEventListener('click', this.handleRootNodeClick) | ||
this.rootNodeRef.removeEventListener('clack', handleClickClack) | ||
} | ||
|
||
render() { | ||
return ( | ||
<div ref={node => this.rootNodeRef = 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
module.exports = { | ||
rules: { | ||
'remove-event-listener': require('./lib/rules/remove-event-listener'), | ||
}, | ||
} |
Oops, something went wrong.