Skip to content

Commit

Permalink
feat: 🎸 add useEvent hook
Browse files Browse the repository at this point in the history
  • Loading branch information
streamich committed Mar 28, 2019
1 parent b20cf7c commit 2a13cfb
Show file tree
Hide file tree
Showing 6 changed files with 118 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
<br/>
<br/>
- [**Lifecycles**](./docs/Lifecycles.md)
- [`useEvent`](./docs/useEvent.md) &mdash; subscribe to events.
- [`useLifecycles`](./docs/useLifecycles.md) &mdash; calls `mount` and `unmount` callbacks.
- [`useRefMounted`](./docs/useRefMounted.md) &mdash; tracks if component is mounted.
- [`usePromise`](./docs/usePromise.md) &mdash; resolves promise only while component is mounted.
Expand Down
38 changes: 38 additions & 0 deletions docs/useEvent.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# `useEvent`

React sensor hook that subscribes a `handler` to events.


## Usage

```jsx
import useEvent from 'react-use/lib/useEvent';
import useList from 'react-use/lib/useList';

const Demo = () => {
const [list, {push}] = useList();
const onkeydown = ({key}) => {
push(key);
};
useEvent('keydown', useCallback(onkeydown, []));

return (
<div>
<p>
Press some keys on your keyboard.
</p>
<pre>
{JSON.stringify(list, null, 4)}
</pre>
</div>
);
};
```


## Examples

```js
useEvent('keydown', handler)
useEvent('scroll', handler, window, {useCapture: true})
```
33 changes: 33 additions & 0 deletions src/__stories__/useEvent.story.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import {storiesOf} from '@storybook/react';
import * as React from 'react';
import {useEvent, useList} from '..';
import ShowDocs from '../util/ShowDocs';
import {CenterStory} from './util/CenterStory';

const {useCallback} = React;

const Demo = () => {
const [list, {push, clear}] = useList();

useEvent('keydown', useCallback(({key}) => {
if (key === 'r') clear();
push(key);
}, []));

return (
<CenterStory>
<p>
Press some keys on your keyboard, <code style={{color: 'tomato'}}>r</code> key resets the list
</p>
<pre>
{JSON.stringify(list, null, 4)}
</pre>
</CenterStory>
);
};

storiesOf('Sensors|useEvent', module)
.add('Docs', () => <ShowDocs md={require('../../docs/useFavicon.md')} />)
.add('Demo', () =>
<Demo />
)
15 changes: 15 additions & 0 deletions src/__stories__/util/CenterStory.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import * as React from 'react';

export const CenterStory = ({children}) => (
<div
style={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
maxWidth: '400px',
margin: '40px auto',
}}
>
<div style={{width: '100%'}}>{children}</div>
</div>
);
2 changes: 2 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import useDropArea from './useDropArea';
import useCounter from './useCounter';
import useCss from './useCss';
import useDebounce from './useDebounce';
import useEvent from './useEvent';
import useFavicon from './useFavicon';
import useGeolocation from './useGeolocation';
import useGetSet from './useGetSet';
Expand Down Expand Up @@ -73,6 +74,7 @@ export {
useCounter,
useCss,
useDebounce,
useEvent,
useFavicon,
useGeolocation,
useGetSet,
Expand Down
29 changes: 29 additions & 0 deletions src/useEvent.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import {useEffect} from 'react';

export interface ListenerType1 {
addEventListener (name: string, handler: (event?: any) => void, ...args: any[]);
removeEventListener (name: string, handler: (event?: any) => void);
}

export interface ListenerType2 {
on (name: string, handler: (event?: any) => void, ...args: any[]);
off (name: string, handler: (event?: any) => void);
}

export type UseEventTarget = ListenerType1 | ListenerType2;

const defaultTarget = typeof window === 'object' ? window : null;

const useEvent = (name: string, handler?: null | undefined | ((event?: any) => void), target: null | UseEventTarget = defaultTarget, options?: any) => {
useEffect(() => {
console.log('adding event...');
if (!handler) return;
if (!target) return;
((target as ListenerType1).addEventListener || (target as ListenerType2).on).call(target, name, handler, options);
return () => {
((target as ListenerType1).removeEventListener || (target as ListenerType2).off).call(target, name, handler, options);
};
}, [name, handler, target, JSON.stringify(options)]);
};

export default useEvent;

0 comments on commit 2a13cfb

Please sign in to comment.