Skip to content
This repository has been archived by the owner on Jan 3, 2024. It is now read-only.

Commit

Permalink
Add remove-event-listener
Browse files Browse the repository at this point in the history
  • Loading branch information
isnifer committed Aug 22, 2018
1 parent f8a6ec4 commit 350464d
Show file tree
Hide file tree
Showing 10 changed files with 2,625 additions and 1 deletion.
12 changes: 12 additions & 0 deletions .editorconfig
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
3 changes: 3 additions & 0 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
node_modules
*.tgz
*~
4 changes: 4 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
language: node_js
node_js:
- "9"
- "8"
5 changes: 4 additions & 1 deletion README.md
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)
203 changes: 203 additions & 0 deletions docs/rules/remove-event-listener.md
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} />
)
}
}
```
5 changes: 5 additions & 0 deletions index.js
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'),
},
}
Loading

0 comments on commit 350464d

Please sign in to comment.