mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Fix validation of AnimatedEvent with AnimatedValueXY
Summary: Changelog: [General][Fixed] Support Animated.ValueXY when validating Animated.event Reviewed By: yungsters Differential Revision: D30779011 fbshipit-source-id: 56f4d9eb6a20200584e5429a1693d0703f8c1a37
This commit is contained in:
committed by
Facebook GitHub Bot
parent
b7c023a8c1
commit
27dd2ecb70
@@ -11,6 +11,7 @@
|
||||
'use strict';
|
||||
|
||||
const AnimatedValue = require('./nodes/AnimatedValue');
|
||||
const AnimatedValueXY = require('./nodes/AnimatedValueXY');
|
||||
const NativeAnimatedHelper = require('./NativeAnimatedHelper');
|
||||
const ReactNative = require('../Renderer/shims/ReactNative');
|
||||
|
||||
@@ -18,7 +19,10 @@ const invariant = require('invariant');
|
||||
|
||||
const {shouldUseNativeDriver} = require('./NativeAnimatedHelper');
|
||||
|
||||
export type Mapping = {[key: string]: Mapping, ...} | AnimatedValue;
|
||||
export type Mapping =
|
||||
| {[key: string]: Mapping, ...}
|
||||
| AnimatedValue
|
||||
| AnimatedValueXY;
|
||||
export type EventConfig = {
|
||||
listener?: ?Function,
|
||||
useNativeDriver: boolean,
|
||||
@@ -41,6 +45,9 @@ function attachNativeEvent(
|
||||
nativeEventPath: path,
|
||||
animatedValueTag: value.__getNativeTag(),
|
||||
});
|
||||
} else if (value instanceof AnimatedValueXY) {
|
||||
traverse(value.x, path.concat('x'));
|
||||
traverse(value.y, path.concat('y'));
|
||||
} else if (typeof value === 'object') {
|
||||
for (const key in value) {
|
||||
traverse(value[key], path.concat(key));
|
||||
@@ -95,6 +102,13 @@ function validateMapping(argMapping, args) {
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (recMapping instanceof AnimatedValueXY) {
|
||||
invariant(
|
||||
typeof recEvt.x === 'number' && typeof recEvt.y === 'number',
|
||||
'Bad mapping of event key ' + key + ', should be XY but got ' + recEvt,
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (typeof recEvt === 'number') {
|
||||
invariant(
|
||||
recMapping instanceof AnimatedValue,
|
||||
@@ -204,22 +218,27 @@ class AnimatedEvent {
|
||||
validatedMapping = true;
|
||||
}
|
||||
|
||||
const traverse = (recMapping, recEvt, key) => {
|
||||
const traverse = (recMapping, recEvt) => {
|
||||
if (recMapping instanceof AnimatedValue) {
|
||||
if (typeof recEvt === 'number') {
|
||||
recMapping.setValue(recEvt);
|
||||
}
|
||||
} else if (recMapping instanceof AnimatedValueXY) {
|
||||
if (typeof recEvt === 'object') {
|
||||
traverse(recMapping.x, recEvt.x);
|
||||
traverse(recMapping.y, recEvt.y);
|
||||
}
|
||||
} else if (typeof recMapping === 'object') {
|
||||
for (const mappingKey in recMapping) {
|
||||
/* $FlowFixMe[prop-missing] (>=0.120.0) This comment suppresses an
|
||||
* error found when Flow v0.120 was deployed. To see the error,
|
||||
* delete this comment and run Flow. */
|
||||
traverse(recMapping[mappingKey], recEvt[mappingKey], mappingKey);
|
||||
traverse(recMapping[mappingKey], recEvt[mappingKey]);
|
||||
}
|
||||
}
|
||||
};
|
||||
this._argMapping.forEach((mapping, idx) => {
|
||||
traverse(mapping, args[idx], 'arg' + idx);
|
||||
traverse(mapping, args[idx]);
|
||||
});
|
||||
|
||||
this._callListeners(...args);
|
||||
|
||||
@@ -638,6 +638,16 @@ describe('Animated tests', () => {
|
||||
handler({bar: 'ignoreBar'}, {state: {baz: 'ignoreBaz', foo: 42}});
|
||||
expect(value.__getValue()).toBe(42);
|
||||
});
|
||||
|
||||
it('should validate AnimatedValueXY mappings', () => {
|
||||
const value = new Animated.ValueXY({x: 0, y: 0});
|
||||
const handler = Animated.event([{state: value}], {
|
||||
useNativeDriver: false,
|
||||
});
|
||||
handler({state: {x: 1, y: 2}});
|
||||
expect(value.__getValue()).toMatchObject({x: 1, y: 2});
|
||||
});
|
||||
|
||||
it('should call listeners', () => {
|
||||
const value = new Animated.Value(0);
|
||||
const listener = jest.fn();
|
||||
@@ -650,6 +660,7 @@ describe('Animated tests', () => {
|
||||
expect(listener.mock.calls.length).toBe(1);
|
||||
expect(listener).toBeCalledWith({foo: 42});
|
||||
});
|
||||
|
||||
it('should call forked event listeners, with Animated.event() listener', () => {
|
||||
const value = new Animated.Value(0);
|
||||
const listener = jest.fn();
|
||||
@@ -666,6 +677,7 @@ describe('Animated tests', () => {
|
||||
expect(listener2.mock.calls.length).toBe(1);
|
||||
expect(listener2).toBeCalledWith({foo: 42});
|
||||
});
|
||||
|
||||
it('should call forked event listeners, with js listener', () => {
|
||||
const listener = jest.fn();
|
||||
const listener2 = jest.fn();
|
||||
@@ -676,6 +688,7 @@ describe('Animated tests', () => {
|
||||
expect(listener2.mock.calls.length).toBe(1);
|
||||
expect(listener2).toBeCalledWith({foo: 42});
|
||||
});
|
||||
|
||||
it('should call forked event listeners, with undefined listener', () => {
|
||||
const listener = undefined;
|
||||
const listener2 = jest.fn();
|
||||
|
||||
@@ -248,6 +248,24 @@ describe('Native Animated', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('shoud map AnimatedValueXY', () => {
|
||||
const value = new Animated.ValueXY({x: 0, y: 0});
|
||||
value.__makeNative();
|
||||
const event = Animated.event([{nativeEvent: {state: value}}], {
|
||||
useNativeDriver: true,
|
||||
});
|
||||
|
||||
TestRenderer.create(<Animated.View onTouchMove={event} />);
|
||||
['x', 'y'].forEach((key, idx) =>
|
||||
expect(
|
||||
NativeAnimatedModule.addAnimatedEventToView,
|
||||
).toHaveBeenNthCalledWith(idx + 1, expect.any(Number), 'onTouchMove', {
|
||||
nativeEventPath: ['state', key],
|
||||
animatedValueTag: value[key].__getNativeTag(),
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw on invalid event path', () => {
|
||||
const value = new Animated.Value(0);
|
||||
value.__makeNative();
|
||||
|
||||
Reference in New Issue
Block a user