Add new `forkEvent`/`unforkEvent` API
Reviewed By: vjeux Differential Revision: D4648427 fbshipit-source-id: 9bbbd81f49a9363ac271b3906d73f937f0d1f500
This commit is contained in:
parent
b7e9374c64
commit
5257c35d05
|
@ -2192,9 +2192,29 @@ function attachNativeEvent(viewRef: any, eventName: string, argMapping: Array<?M
|
|||
};
|
||||
}
|
||||
|
||||
function forkEvent(event: ?AnimatedEvent | ?Function, listener: Function): AnimatedEvent | Function {
|
||||
if (!event) {
|
||||
return listener;
|
||||
} else if (event instanceof AnimatedEvent) {
|
||||
event.__addListener(listener);
|
||||
return event;
|
||||
} else {
|
||||
return (...args) => {
|
||||
typeof event === 'function' && event(...args);
|
||||
listener(...args);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function unforkEvent(event: ?AnimatedEvent | ?Function, listener: Function): void {
|
||||
if (event && event instanceof AnimatedEvent) {
|
||||
event.__removeListener(listener);
|
||||
}
|
||||
}
|
||||
|
||||
class AnimatedEvent {
|
||||
_argMapping: Array<?Mapping>;
|
||||
_listener: ?Function;
|
||||
_listeners: Array<Function> = [];
|
||||
_attachedEvent: ?{
|
||||
detach: () => void,
|
||||
};
|
||||
|
@ -2205,7 +2225,9 @@ class AnimatedEvent {
|
|||
config?: EventConfig = {}
|
||||
) {
|
||||
this._argMapping = argMapping;
|
||||
this._listener = config.listener;
|
||||
if (config.listener) {
|
||||
this.__addListener(config.listener);
|
||||
}
|
||||
this._attachedEvent = null;
|
||||
this.__isNative = shouldUseNativeDriver(config);
|
||||
|
||||
|
@ -2214,6 +2236,14 @@ class AnimatedEvent {
|
|||
}
|
||||
}
|
||||
|
||||
__addListener(callback: Function): void {
|
||||
this._listeners.push(callback);
|
||||
}
|
||||
|
||||
__removeListener(callback: Function): void {
|
||||
this._listeners = this._listeners.filter((listener) => listener !== callback);
|
||||
}
|
||||
|
||||
__attach(viewRef, eventName) {
|
||||
invariant(this.__isNative, 'Only native driven events need to be attached.');
|
||||
|
||||
|
@ -2228,7 +2258,7 @@ class AnimatedEvent {
|
|||
|
||||
__getHandler() {
|
||||
if (this.__isNative) {
|
||||
return this._listener;
|
||||
return this._callListeners;
|
||||
}
|
||||
|
||||
return (...args) => {
|
||||
|
@ -2247,13 +2277,14 @@ class AnimatedEvent {
|
|||
traverse(mapping, args[idx], 'arg' + idx);
|
||||
});
|
||||
}
|
||||
|
||||
if (this._listener) {
|
||||
this._listener.apply(null, args);
|
||||
}
|
||||
this._callListeners(...args);
|
||||
};
|
||||
}
|
||||
|
||||
_callListeners = (...args) => {
|
||||
this._listeners.forEach(listener => listener(...args));
|
||||
};
|
||||
|
||||
_validateMapping() {
|
||||
const traverse = (recMapping, recEvt, key) => {
|
||||
if (typeof recEvt === 'number') {
|
||||
|
@ -2602,5 +2633,12 @@ module.exports = {
|
|||
*/
|
||||
attachNativeEvent,
|
||||
|
||||
/**
|
||||
* Advanced imperative API for snooping on animated events that are passed in through props. Use
|
||||
* values directly where possible.
|
||||
*/
|
||||
forkEvent,
|
||||
unforkEvent,
|
||||
|
||||
__PropsOnlyForTests: AnimatedProps,
|
||||
};
|
||||
|
|
|
@ -353,6 +353,22 @@ describe('Animated tests', () => {
|
|||
expect(listener.mock.calls.length).toBe(1);
|
||||
expect(listener).toBeCalledWith({foo: 42});
|
||||
});
|
||||
it('should call forked event listeners', () => {
|
||||
var value = new Animated.Value(0);
|
||||
var listener = jest.fn();
|
||||
var handler = Animated.event(
|
||||
[{foo: value}],
|
||||
{listener},
|
||||
);
|
||||
var listener2 = jest.fn();
|
||||
var forkedHandler = Animated.forkEvent(handler, listener2);
|
||||
forkedHandler({foo: 42});
|
||||
expect(value.__getValue()).toBe(42);
|
||||
expect(listener.mock.calls.length).toBe(1);
|
||||
expect(listener).toBeCalledWith({foo: 42});
|
||||
expect(listener2.mock.calls.length).toBe(1);
|
||||
expect(listener2).toBeCalledWith({foo: 42});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Animated Interactions', () => {
|
||||
|
|
Loading…
Reference in New Issue