Skip to content

💩 update #32

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
src
__tests__
coverage

.husky
tsconfig.json
.travis.yml
.prettierrc

.eslintrc.js
rollup.config.js
yarn-error.log
Expand Down
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@

## 1.0.0 (Soon)

#### New Feature
### New Feature

- added `useCustomEvent`, `useEmitter` & `useListener` hooks
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
[![NPM downloads](https://img.shields.io/npm/dm/react-custom-events-hooks?style=flat-square)](https://www.npmjs.com/package/react-custom-events-hooks)
[![NPM license](https://img.shields.io/npm/l/react-custom-events-hooks?style=flat-square)](https://www.npmjs.com/package/react-custom-events-hooks)
[![Codecov](https://img.shields.io/codecov/c/github/cool-hooks/react-custom-events-hooks?style=flat-square)](https://codecov.io/gh/cool-hooks/react-custom-events-hooks)
[![Travis](https://img.shields.io/travis/cool-hooks/react-custom-events-hooks/master?style=flat-square)](https://travis-ci.org/cool-hooks/react-custom-events-hooks)
[![Travis](https://img.shields.io/travis/com/cool-hooks/react-custom-events-hooks/master?style=flat-square)](https://app.travis-ci.com/github/cool-hooks/react-custom-events-hooks)
[![Bundle size](https://img.shields.io/bundlephobia/min/react-custom-events-hooks?style=flat-square)](https://bundlephobia.com/result?p=react-custom-events-hooks)

## About
Expand Down Expand Up @@ -33,7 +33,7 @@ $ yarn add react-custom-events-hooks

## Getting Started

**• Import hooks in React application file:**
**• Import hooks in the React application file:**

```js
import {
Expand All @@ -43,7 +43,7 @@ import {
} from 'react-custom-events-hooks';
```

#### Example
### Example

```js
import React, { useState } from 'react';
Expand Down
7 changes: 5 additions & 2 deletions __tests__/useCustomEvent.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ import { renderHook } from '@testing-library/react-hooks';
import { useCustomEvent } from '../src';

describe('useCustomEvent', () => {
it('should', () => {
it('should emit custom event', () => {
const { result } = renderHook(() =>
useCustomEvent({ eventName: 'myAwesomeCustomEvent' })
);

result.current('hello');
});

it('should', () => {
it('should emit and listen to custom event', () => {
const onSignal = jest.fn();

const { result } = renderHook(() =>
Expand All @@ -34,4 +34,7 @@ describe('useCustomEvent', () => {
message: 'world',
});
});

it.todo('custom element');
it.todo('options');
});
27 changes: 24 additions & 3 deletions __tests__/useEmitter.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,37 @@ import { renderHook } from '@testing-library/react-hooks';

import { useEmitter } from '../src';

// TODO refactor
describe('useEmitter', () => {
it('should', () => {
it('should emit custom event', () => {
const { result } = renderHook(() => useEmitter('myAwesomeCustomEvent'));

result.current({
title: 'hello',
});

window.addEventListener('myAwesomeCustomEvent', (e) => {
expect(e.detail).toStrictEqual({
title: 'hello',
});
});
});

it('should', () => {
const { result } = renderHook(() => null);
it('should emit custom event on element', () => {
const element = document.createElement('div');

const { result } = renderHook(() =>
useEmitter('myAwesomeCustomEvent', element)
);

result.current({
title: 'hello',
});

element.addEventListener('myAwesomeCustomEvent', (e) => {
expect(e.detail).toStrictEqual({
title: 'hello',
});
});
});
});
94 changes: 79 additions & 15 deletions __tests__/useListener.test.ts
Original file line number Diff line number Diff line change
@@ -1,37 +1,101 @@
import { renderHook } from '@testing-library/react-hooks';

import { useCustomEvent, useListener } from '../src';
import { useListener } from '../src';

describe('useListener', () => {
it('should', () => {
const { result } = renderHook(() =>
useCustomEvent({ eventName: 'myAwesomeCustomEvent' })
);
// it('should', () => {
// const onSignal = jest.fn();

result.current('hello');
});
// const { result } = renderHook(() =>
// useListener({
// eventName: 'myAwesomeCustomEvent',
// defaultValue: {
// sender: 'dummy-sender',
// },
// onSignal,
// })
// );

// result.current({
// title: 'hello',
// message: 'world',
// });

// expect(onSignal).toHaveBeenCalledWith({
// title: 'hello',
// message: 'world',
// });
// });

it('should', () => {
it('should call onSignal when custom event is emitted', () => {
const onSignal = jest.fn();

const { result } = renderHook(() =>
useCustomEvent({
renderHook(() =>
useListener({
eventName: 'myAwesomeCustomEvent',
defaultValue: {
sender: 'dummy-sender',
},
onSignal,
})
);

result.current({
window.dispatchEvent(
new CustomEvent('myAwesomeCustomEvent', {
detail: {
title: 'hello',
message: 'world',
},
})
);

expect(onSignal).toHaveBeenCalledWith({
title: 'hello',
message: 'world',
});
});

expect(onSignal).toHaveBeenCalledWith({
// it.todo('onSignal call')
// it.todo('no onSignal') ?

// TODO custom element
it('should ', () => {
const onSignalElement = jest.fn();
const onSignalWindow = jest.fn();

const element = document.createElement('div');

renderHook(() =>
useListener({
eventName: 'myAwesomeCustomEvent',
onSignal: onSignalElement,
element,
})
);

renderHook(() =>
useListener({
eventName: 'myAwesomeCustomEvent',
onSignal: onSignalWindow,
})
);

element.dispatchEvent(
new CustomEvent('myAwesomeCustomEvent', {
detail: {
title: 'hello',
message: 'world',
},
})
);

expect(onSignalElement).toHaveBeenCalledWith({
title: 'hello',
message: 'world',
});

expect(onSignalWindow).not.toHaveBeenCalled();
});

it.todo('multiple calls one by one');

// it.todo('custom element')
it.todo('options');
});
19 changes: 8 additions & 11 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "react-custom-events-hooks",
"version": "0.1.0",
"version": "1.0.0",
"description": "Create custom events. Fast, simple, fun!",
"author": "Jakub Biesiada",
"license": "MIT",
Expand All @@ -17,19 +17,22 @@
"lint": "eslint 'src/**/*.{tsx,ts}' --fix",
"prettier": "prettier --write 'src/**/*.{tsx,ts}'",
"commit": "git-cz",
"semantic-release": "semantic-release"
"semantic-release": "semantic-release",
"prepare": "husky install",
"pre-commit": "lint-staged"
},
"repository": {
"type": "git",
"url": "https://github.com/cool-hooks/react-custom-events-hooks.git"
},
"keywords": [
"react",
"hooks",
"events",
"emitter",
"listener",
"observable",
"hooks"
"listener",
"signals",
"emitter"
],
"bugs": {
"url": "https://github.com/cool-hooks/react-custom-events-hooks/issues"
Expand All @@ -41,7 +44,6 @@
"@testing-library/react-hooks": "^3.4.2",
"@types/jest": "^26.0.15",
"@types/react": "^16.9.56",
"@types/react-router": "^5.1.8",
"@typescript-eslint/parser": "^4.7.0",
"cz-conventional-changelog": "3.3.0",
"cz-emoji": "^1.3.1",
Expand Down Expand Up @@ -77,11 +79,6 @@
"^.+\\.tsx?$": "ts-jest"
}
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"src/**/*.{tsx,ts}": [
"npm run prettier",
Expand Down
2 changes: 1 addition & 1 deletion rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,5 @@ export default {
},
],
plugins: [resolve(), typescript(), terser()],
external: Object.keys(pkg.peerDependencies),
external: Object.keys(pkg.peerDependencies || {}),
};
15 changes: 5 additions & 10 deletions src/hooks/useCustomEvent.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,19 @@
import { useMemo } from 'react';

import { useListener } from './useListener';
import { useEmitter } from './useEmitter';

import type { Element, Options } from '../types';

interface Params<T> {
readonly eventName: string;
onSignal?: (e: CustomEvent<T>) => void;
readonly element?: Element;
readonly options?: Options;
}
import type { Params } from '../types';

export const useCustomEvent = <T>({
eventName,
onSignal,
element = window,
options = {},
}: Params<T>) => {
const handleSignal = onSignal || (() => null);
const handleSignal = useMemo(() => onSignal || (() => null), [onSignal]);

useListener<T>(eventName, handleSignal, element, options);
useListener<T>({ eventName, onSignal: handleSignal, element, options });

return useEmitter<T>(eventName, element);
};
25 changes: 19 additions & 6 deletions src/hooks/useEmitter.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,24 @@
import type { Element } from '../types';
import { useCallback } from 'react';

export const useEmitter = <T>(eventName: string, element: Element = window) => {
const callEvent = (data: T) => {
const event = new CustomEvent(eventName, { detail: data });
import type { ObservedElement } from '../types';

element.dispatchEvent(event);
};
type CallEventCallback<T> = (data: T) => void;

export const useEmitter = <T>(
eventName: string,
element: ObservedElement = window
) => {
// TODO add options
const callEvent = useCallback<CallEventCallback<T>>(
(data) => {
const event = new CustomEvent(eventName, {
detail: data /* ...options */,
});

element.dispatchEvent(event);
},
[element, eventName]
);

return callEvent;
};
18 changes: 8 additions & 10 deletions src/hooks/useListener.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
import { useEffect } from 'react';

import type { Element, Options } from '../types';
import type { Params } from '../types';

export const useListener = <T>(
eventName: string,
onSignal: (e: CustomEvent<T>) => void,
element: Element = window,
options: Options = {}
) => {
export const useListener = <T>({
eventName,
onSignal,
element = window,
options = {},
}: Params<T>) => {
useEffect(() => {
if (typeof onSignal === 'function') {
const handleSignal = (e: Event) => {
onSignal(e as CustomEvent);
};
const handleSignal = (e: Event) => onSignal(e as CustomEvent);

element.addEventListener(eventName, handleSignal, options);

Expand Down
1 change: 0 additions & 1 deletion src/types/Element.ts

This file was deleted.

1 change: 1 addition & 0 deletions src/types/ObservedElement.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export type ObservedElement = HTMLElement | Window | Document;
1 change: 0 additions & 1 deletion src/types/Options.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
/* eslint-disable no-undef */
export type Options = boolean | AddEventListenerOptions;
8 changes: 8 additions & 0 deletions src/types/Params.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import type { ObservedElement, Options } from '.';

export interface Params<T> {
readonly eventName: string;
readonly onSignal: (e: CustomEvent<T>) => void;
readonly element: ObservedElement;
readonly options: Options;
}
Loading