Skip to content

Commit 9e63c49

Browse files
committed
[event] Adds event hook
1 parent 24bd7c1 commit 9e63c49

19 files changed

+6715
-0
lines changed

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,13 @@ A counter implemented as a React hook.
2929

3030
A React hook for debouncing setState and other callbacks.
3131

32+
#### useEvent() [`@react-hook/event`](packages/event)
33+
34+
A React hook for adding events to HTML elements. This hook cleans up your listeners
35+
automatically when it unmounts. You won't have to worry about wrapping your
36+
listener in a `useCallback()` because this hook makes sure your most recent callback
37+
is always invoked.
38+
3239
#### useGoogleOptimize() [`@react-hook/google-optimize`](packages/google-optimize)
3340

3441
A React hook for adding Google Optimize variants to components.

packages/event/.eslintignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
node_modules
2+
/coverage
3+
/dist
4+
/test
5+
*.config.js

packages/event/.eslintrc

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
{
2+
"parser": "@typescript-eslint/parser",
3+
"parserOptions": {
4+
"ecmaFeatures": {
5+
"jsx": true
6+
}
7+
},
8+
"plugins": ["@typescript-eslint", "jest", "react", "react-hooks"],
9+
"extends": [
10+
"eslint:recommended",
11+
"plugin:react/recommended",
12+
"plugin:jest/recommended",
13+
"plugin:@typescript-eslint/recommended"
14+
],
15+
"rules": {
16+
"@typescript-eslint/member-delimiter-style": "off",
17+
"@typescript-eslint/interface-name-prefix": "off",
18+
"@typescript-eslint/no-explicit-any": "off",
19+
"@typescript-eslint/ban-ts-ignore": "off",
20+
"@typescript-eslint/camelcase": "off",
21+
"@typescript-eslint/explicit-function-return-type": "off",
22+
"@typescript-eslint/no-use-before-define": "off",
23+
"@typescript-eslint/explicit-module-boundary-types": "off",
24+
"no-console": "off",
25+
"no-prototype-builtins": "off",
26+
"react/no-children-prop": "off",
27+
"react/display-name": "off",
28+
"react/prop-types": "off",
29+
"react-hooks/rules-of-hooks": "error",
30+
"react-hooks/exhaustive-deps": "warn"
31+
},
32+
"settings": {
33+
"react": {
34+
"pragma": "React",
35+
"version": "detect"
36+
}
37+
},
38+
"env": {
39+
"browser": true,
40+
"node": true,
41+
"es6": true,
42+
"jest/globals": true
43+
},
44+
"globals": {
45+
"__DEV__": true
46+
},
47+
"overrides": [
48+
{
49+
"files": ["**/test.ts", "**/*.test.ts", "**/test.tsx", "**/*.test.tsx"],
50+
"settings": {
51+
"import/resolver": {
52+
"jest": {
53+
"jestConfigFile": "./jest.config.js"
54+
}
55+
}
56+
}
57+
}
58+
]
59+
}

packages/event/.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
node_modules
2+
dist
3+
coverage
4+
*.log

packages/event/.prettierignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
node_modules
2+
/coverage

packages/event/.prettierrc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"trailingComma": "es5",
3+
"tabWidth": 2,
4+
"semi": false,
5+
"singleQuote": true,
6+
"bracketSpacing": false
7+
}

packages/event/.travis.yml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
sudo: false
2+
language: node_js
3+
cache:
4+
yarn: true
5+
directories:
6+
- node_modules
7+
notifications:
8+
email: false
9+
node_js: '12'
10+
install: yarn install
11+
script: yarn validate
12+
after_script: npx codecov@3
13+
branches:
14+
only:
15+
- master

packages/event/LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2019 Jared Lunde
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

packages/event/README.md

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
<hr>
2+
<div align="center">
3+
<h1 align="center">
4+
useEvent()
5+
</h1>
6+
</div>
7+
8+
<p align="center">
9+
<a href="https://bundlephobia.com/result?p=@react-hook/event">
10+
<img alt="Bundlephobia" src="https://img.shields.io/bundlephobia/minzip/@react-hook/event?style=for-the-badge&labelColor=24292e">
11+
</a>
12+
<a aria-label="Types" href="https://www.npmjs.com/package/@react-hook/event">
13+
<img alt="Types" src="https://img.shields.io/npm/types/@react-hook/event?style=for-the-badge&labelColor=24292e">
14+
</a>
15+
<!--
16+
<a aria-label="Code coverage report" href="https://codecov.io/gh/jaredLunde/react-hook">
17+
<img alt="Code coverage" src="https://img.shields.io/codecov/c/gh/jaredLunde/react-hook?style=for-the-badge&labelColor=24292e">
18+
</a>
19+
<a aria-label="Build status" href="https://travis-ci.com/jaredLunde/react-hook">
20+
<img alt="Build status" src="https://img.shields.io/travis/com/jaredLunde/react-hook?style=for-the-badge&labelColor=24292e">
21+
</a>
22+
-->
23+
<a aria-label="NPM version" href="https://www.npmjs.com/package/@react-hook/event">
24+
<img alt="NPM Version" src="https://img.shields.io/npm/v/@react-hook/event?style=for-the-badge&labelColor=24292e">
25+
</a>
26+
<a aria-label="License" href="https://jaredlunde.mit-license.org/">
27+
<img alt="MIT License" src="https://img.shields.io/npm/l/@react-hook/event?style=for-the-badge&labelColor=24292e">
28+
</a>
29+
</p>
30+
31+
<pre align="center">npm i @react-hook/event</pre>
32+
<hr>
33+
34+
A React hook for adding events to HTML elements. This hook cleans up your listeners
35+
automatically when it unmounts. You won't have to worry about wrapping your
36+
listener in a `useCallback()` because this hook makes sure your most recent callback
37+
is always invoked.
38+
39+
## Quick Start
40+
41+
```jsx harmony
42+
import * as React from 'react'
43+
import useEvent from '@react-hook/event'
44+
45+
// Logs an event each time target.current is clicked
46+
const Component = () => {
47+
const target = useRef(null)
48+
useEvent(target, 'click', (event) => console.log(event))
49+
return <div ref={target} />
50+
}
51+
52+
// Logs an event each time the `document` is clicked
53+
const DocumentComponent = () => {
54+
const target = useRef(null)
55+
useEvent(document, 'click', (event) => console.log(event))
56+
return <div ref={target} />
57+
}
58+
59+
// Logs an event each time the `window` is clicked
60+
const WindowComponent = () => {
61+
const target = useRef(null)
62+
useEvent(window, 'click', (event) => console.log(event))
63+
return <div ref={target} />
64+
}
65+
```
66+
67+
## API
68+
69+
### useEvent(target, type, listener)
70+
71+
```ts
72+
const useEvent = <
73+
T extends HTMLElement = HTMLElement,
74+
K extends keyof HTMLElementEventMap = keyof HTMLElementEventMap
75+
>(
76+
target: React.RefObject<T> | Window | Document,
77+
type: K,
78+
listener: EventListener<K>
79+
)
80+
```
81+
82+
| Argument | Type | Required? | Description |
83+
| -------- | ------------------------------------------------------------------- | --------- | ------------------------------------------------------------------- |
84+
| target | <code>React.RefObject&lt;T&gt; &#124; Window &#124; Document</code> | Yes | The React ref, `window`, or `document` to add the event listener to |
85+
| type | `keyof HTMLElementEventMap` | Yes | The type of event to listen for |
86+
| listener | `(this: HTMLElement, ev: HTMLElementEventMap[K]) => any` | Yes | The callback invoked when the event type fires |
87+
88+
## LICENSE
89+
90+
MIT

packages/event/babel.config.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
module.exports = (api) => {
2+
const module = api.env('module')
3+
const esm = api.env('esm')
4+
const presetEnv = [
5+
'@lunde/es',
6+
{
7+
env: {
8+
modules: esm || module ? false : 'commonjs',
9+
targets: module
10+
? {
11+
browsers: '> 2%',
12+
}
13+
: {
14+
node: esm ? '12' : '10',
15+
},
16+
},
17+
restSpread: false,
18+
devExpression: false,
19+
objectAssign: false,
20+
},
21+
]
22+
23+
return {
24+
presets: [['@babel/preset-react', {useSpread: true}], presetEnv],
25+
plugins: ['optimize-react', 'annotate-pure-calls'],
26+
}
27+
}

packages/event/jest.config.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
const path = require('path')
2+
3+
module.exports = {
4+
// testEnvironment: 'jest-environment-jsdom',
5+
moduleDirectories: [
6+
'node_modules',
7+
path.join(__dirname, 'src'),
8+
path.join(__dirname, 'test'),
9+
],
10+
testMatch: ['<rootDir>/src/**/?(*.)test.{ts,tsx}'],
11+
collectCoverageFrom: ['**/src/**/*.{ts,tsx}'],
12+
// moduleNameMapper: {},
13+
setupFilesAfterEnv: [require.resolve('./test/setup.js')],
14+
snapshotResolver: require.resolve('./test/resolve-snapshot.js'),
15+
// coverageThreshold: {
16+
// global: {
17+
// statements:17,
18+
// branches: 4,
19+
// lines: 17,
20+
// functions: 20
21+
// }
22+
// },
23+
globals: {
24+
__DEV__: true,
25+
},
26+
}

packages/event/package.json

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
{
2+
"name": "@react-hook/event",
3+
"version": "1.0.0",
4+
"homepage": "https://github.com/jaredLunde/react-hook/tree/master/packages/event#readme",
5+
"repository": "github:jaredLunde/react-hook",
6+
"bugs": "https://github.com/jaredLunde/react-hook/issues",
7+
"author": "Jared Lunde <jared.lunde@gmail.com> (https://jaredLunde.com)",
8+
"license": "MIT",
9+
"description": "A React hook for managing event listeners, e.g. removing events when a component unmounts.",
10+
"keywords": [
11+
"react",
12+
"react hook",
13+
"use-event",
14+
"use-events",
15+
"react event hook",
16+
"react events hook",
17+
"react listener hook",
18+
"event hook",
19+
"events hook"
20+
],
21+
"main": "dist/main/index.js",
22+
"module": "dist/module/index.js",
23+
"source": "src/index.tsx",
24+
"types": "types/index.d.ts",
25+
"files": [
26+
"/dist",
27+
"/src",
28+
"/types"
29+
],
30+
"exports": {
31+
".": {
32+
"browser": "./dist/module/index.js",
33+
"import": "./dist/esm/index.mjs",
34+
"require": "./dist/main/index.js",
35+
"source": "./src/index.tsx",
36+
"types": "./types/index.d.ts",
37+
"default": "./dist/main/index.js"
38+
},
39+
"./package.json": "./package.json",
40+
"./": "./"
41+
},
42+
"sideEffects": false,
43+
"scripts": {
44+
"build": "npm run build-esm && npm run build-main && npm run build-module && npm run build-types",
45+
"build-esm": "npm run compile -- -d dist/esm --env-name esm --out-file-extension .mjs",
46+
"build-main": "npm run compile -- -d dist/main --env-name main",
47+
"build-module": "npm run compile -- -d dist/module --env-name module",
48+
"build-types": "tsc -p tsconfig.json -d --outDir types --emitDeclarationOnly",
49+
"check-types": "tsc --noEmit -p tsconfig.json",
50+
"compile": "babel src -x .ts,.tsx --ignore \"**/*.test.ts\",\"**/*.test.tsx\" --delete-dir-on-start",
51+
"format": "prettier --write \"**/*.{ts,tsx,js,jsx,md,yml,json,eslintrc,prettierrc}\"",
52+
"lint": "eslint . --ext .ts,.tsx",
53+
"prepublishOnly": "npm run lint && npm run test && npm run build && npm run format",
54+
"test": "jest",
55+
"validate": "npm run check-types && npm run lint && npm run test -- --coverage"
56+
},
57+
"husky": {
58+
"hooks": {
59+
"pre-commit": "npm run build-types && prettier --write \"types/**/*.ts\" && lint-staged"
60+
}
61+
},
62+
"lint-staged": {
63+
"**/*.{ts,tsx,js,jsx}": [
64+
"eslint",
65+
"prettier --write"
66+
],
67+
"**/*.{md,yml,json,eslintrc,prettierrc}": [
68+
"prettier --write"
69+
]
70+
},
71+
"devDependencies": {
72+
"@babel/preset-react": "latest",
73+
"@lunde/babel-preset-es": "latest",
74+
"@testing-library/jest-dom": "latest",
75+
"@testing-library/react": "latest",
76+
"@testing-library/react-hooks": "latest",
77+
"@types/jest": "latest",
78+
"@types/react": "latest",
79+
"@types/react-dom": "latest",
80+
"@typescript-eslint/eslint-plugin": "latest",
81+
"@typescript-eslint/parser": "latest",
82+
"babel-plugin-annotate-pure-calls": "latest",
83+
"babel-plugin-optimize-react": "latest",
84+
"eslint": "latest",
85+
"eslint-import-resolver-jest": "latest",
86+
"eslint-plugin-jest": "latest",
87+
"eslint-plugin-react": "latest",
88+
"eslint-plugin-react-hooks": "latest",
89+
"husky": "latest",
90+
"jest": "latest",
91+
"lint-staged": "latest",
92+
"prettier": "latest",
93+
"react": "latest",
94+
"react-dom": "latest",
95+
"react-test-renderer": "latest",
96+
"ts-jest": "latest",
97+
"typescript": "latest"
98+
},
99+
"dependencies": {
100+
"@react-hook/passive-layout-effect": "^1.0.3"
101+
},
102+
"peerDependencies": {
103+
"prop-types": ">=15.6",
104+
"react": ">=16.8",
105+
"react-dom": ">=16.8"
106+
}
107+
}

0 commit comments

Comments
 (0)