Add new `forkEvent`/`unforkEvent` API
Reviewed By: vjeux Differential Revision: D4648427 fbshipit-source-id: 9bbbd81f49a9363ac271b3906d73f937f0d1f500
This commit is contained in:
Родитель
b7e9374c64
Коммит
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 {
|
class AnimatedEvent {
|
||||||
_argMapping: Array<?Mapping>;
|
_argMapping: Array<?Mapping>;
|
||||||
_listener: ?Function;
|
_listeners: Array<Function> = [];
|
||||||
_attachedEvent: ?{
|
_attachedEvent: ?{
|
||||||
detach: () => void,
|
detach: () => void,
|
||||||
};
|
};
|
||||||
|
@ -2205,7 +2225,9 @@ class AnimatedEvent {
|
||||||
config?: EventConfig = {}
|
config?: EventConfig = {}
|
||||||
) {
|
) {
|
||||||
this._argMapping = argMapping;
|
this._argMapping = argMapping;
|
||||||
this._listener = config.listener;
|
if (config.listener) {
|
||||||
|
this.__addListener(config.listener);
|
||||||
|
}
|
||||||
this._attachedEvent = null;
|
this._attachedEvent = null;
|
||||||
this.__isNative = shouldUseNativeDriver(config);
|
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) {
|
__attach(viewRef, eventName) {
|
||||||
invariant(this.__isNative, 'Only native driven events need to be attached.');
|
invariant(this.__isNative, 'Only native driven events need to be attached.');
|
||||||
|
|
||||||
|
@ -2228,7 +2258,7 @@ class AnimatedEvent {
|
||||||
|
|
||||||
__getHandler() {
|
__getHandler() {
|
||||||
if (this.__isNative) {
|
if (this.__isNative) {
|
||||||
return this._listener;
|
return this._callListeners;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (...args) => {
|
return (...args) => {
|
||||||
|
@ -2247,13 +2277,14 @@ class AnimatedEvent {
|
||||||
traverse(mapping, args[idx], 'arg' + idx);
|
traverse(mapping, args[idx], 'arg' + idx);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
this._callListeners(...args);
|
||||||
if (this._listener) {
|
|
||||||
this._listener.apply(null, args);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_callListeners = (...args) => {
|
||||||
|
this._listeners.forEach(listener => listener(...args));
|
||||||
|
};
|
||||||
|
|
||||||
_validateMapping() {
|
_validateMapping() {
|
||||||
const traverse = (recMapping, recEvt, key) => {
|
const traverse = (recMapping, recEvt, key) => {
|
||||||
if (typeof recEvt === 'number') {
|
if (typeof recEvt === 'number') {
|
||||||
|
@ -2602,5 +2633,12 @@ module.exports = {
|
||||||
*/
|
*/
|
||||||
attachNativeEvent,
|
attachNativeEvent,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Advanced imperative API for snooping on animated events that are passed in through props. Use
|
||||||
|
* values directly where possible.
|
||||||
|
*/
|
||||||
|
forkEvent,
|
||||||
|
unforkEvent,
|
||||||
|
|
||||||
__PropsOnlyForTests: AnimatedProps,
|
__PropsOnlyForTests: AnimatedProps,
|
||||||
};
|
};
|
||||||
|
|
|
@ -353,6 +353,22 @@ describe('Animated tests', () => {
|
||||||
expect(listener.mock.calls.length).toBe(1);
|
expect(listener.mock.calls.length).toBe(1);
|
||||||
expect(listener).toBeCalledWith({foo: 42});
|
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', () => {
|
describe('Animated Interactions', () => {
|
||||||
|
|
Загрузка…
Ссылка в новой задаче