From 71f4ef1a928657ff0c2dbfb296d0701200b202e6 Mon Sep 17 00:00:00 2001 From: "satyajit.happy" Date: Tue, 6 Aug 2019 17:49:18 +0200 Subject: [PATCH] refactor: standardize event argument --- README.md | 2 ++ .../src/__tests__/useEventEmitter.test.tsx | 13 +++++++---- packages/core/src/types.tsx | 18 ++++++++++----- packages/core/src/useEventEmitter.tsx | 23 +++++++++++++++++-- 4 files changed, 43 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index e483e838..713cdc3f 100644 --- a/README.md +++ b/README.md @@ -220,6 +220,8 @@ navigation.emit({ }); ``` +The `data` is available under the `data` property in the `event` object, i.e. `event.data`. + The `target` property determines the screen that will receive the event. If the `target` property is omitted, the event is dispatched to all screens in the navigator. Screens cannot emit events as there is no `emit` method on a screen's `navigation` prop. diff --git a/packages/core/src/__tests__/useEventEmitter.test.tsx b/packages/core/src/__tests__/useEventEmitter.test.tsx index ac988e1d..22950f1c 100644 --- a/packages/core/src/__tests__/useEventEmitter.test.tsx +++ b/packages/core/src/__tests__/useEventEmitter.test.tsx @@ -247,20 +247,23 @@ it('fires custom events', () => { expect(secondCallback).toBeCalledTimes(0); expect(thirdCallback).toBeCalledTimes(0); - act(() => + act(() => { ref.current.navigation.emit({ type: eventName, target: ref.current.state.routes[ref.current.state.routes.length - 1].key, data: 42, - }) - ); + }); + }); expect(firstCallback).toBeCalledTimes(0); expect(secondCallback).toBeCalledTimes(0); expect(thirdCallback).toBeCalledTimes(1); - expect(thirdCallback.mock.calls[0][0]).toBe(42); + expect(thirdCallback.mock.calls[0][0].type).toBe('someSuperCoolEvent'); + expect(thirdCallback.mock.calls[0][0].data).toBe(42); - act(() => ref.current.navigation.emit({ type: eventName })); + act(() => { + ref.current.navigation.emit({ type: eventName }); + }); expect(firstCallback).toBeCalledTimes(1); expect(secondCallback).toBeCalledTimes(1); diff --git a/packages/core/src/types.tsx b/packages/core/src/types.tsx index f3ec934c..39680d56 100644 --- a/packages/core/src/types.tsx +++ b/packages/core/src/types.tsx @@ -160,18 +160,24 @@ export type EventMapBase = { blur: undefined; }; -export type EventListenerCallback = Data extends undefined - ? () => void - : (data: Data) => void; +export type EventArg = { + readonly type: EventName; + readonly defaultPrevented: boolean; + preventDefault(): void; +} & (Data extends undefined ? {} : { readonly data: Data }); + +export type EventListenerCallback = ( + e: EventArg +) => void; export type EventConsumer = { addListener>( type: EventName, - callback: EventListenerCallback + callback: EventListenerCallback ): () => void; removeListener>( type: EventName, - callback: EventListenerCallback + callback: EventListenerCallback ): void; }; @@ -180,7 +186,7 @@ export type EventEmitter = { type: EventName; data?: EventMap[EventName]; target?: string; - }): void; + }): EventArg; }; class PrivateValueStore { diff --git a/packages/core/src/useEventEmitter.tsx b/packages/core/src/useEventEmitter.tsx index 2d46816c..6ddbe3a5 100644 --- a/packages/core/src/useEventEmitter.tsx +++ b/packages/core/src/useEventEmitter.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import { EventEmitter, EventConsumer } from './types'; +import { EventEmitter, EventConsumer, EventArg } from './types'; export type NavigationEventEmitter = EventEmitter<{ [key: string]: any }> & { create: (target: string) => EventConsumer<{ [key: string]: any }>; @@ -51,7 +51,26 @@ export default function useEventEmitter(): NavigationEventEmitter { ? items[target] && items[target].slice() : ([] as Listeners).concat(...Object.keys(items).map(t => items[t])); - callbacks && callbacks.forEach(cb => cb(data)); + let defaultPrevented = false; + + const event: EventArg = { + get type() { + return type; + }, + get data() { + return data; + }, + get defaultPrevented() { + return defaultPrevented; + }, + preventDefault() { + defaultPrevented = true; + }, + }; + + callbacks && callbacks.forEach(cb => cb(event)); + + return event; }, [] );