Skip to content

Commit 0a6aca9

Browse files
yungstersfacebook-github-bot
authored andcommitted
Animated: Trigger Callback on Stopping Native Loops (#52274)
Summary: Currently, `callback` in `Animated.loop(animation).start(callback)` does not get triggered when calling `stop()` if `animation` uses native driver. This diff implements that functionality. Changelog: [General][Changed] - Stopping an `Animated.loop` for a native animation will now correctly trigger completion callbacks supplied to `start()`. Differential Revision: D77329013
1 parent c660868 commit 0a6aca9

File tree

3 files changed

+34
-9
lines changed

3 files changed

+34
-9
lines changed

packages/react-native/Libraries/Animated/AnimatedImplementation.js

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ export type CompositeAnimation = {
4242
start: (callback?: ?EndCallback, isLooping?: boolean) => void,
4343
stop: () => void,
4444
reset: () => void,
45-
_startNativeLoop: (iterations?: number) => void,
45+
_startNativeLoop: (iterations: number, callback: ?EndCallback) => void,
4646
_isUsingNativeDriver: () => boolean,
4747
...
4848
};
@@ -192,9 +192,9 @@ const springImpl = function (
192192
value.resetAnimation();
193193
},
194194

195-
_startNativeLoop: function (iterations?: number): void {
195+
_startNativeLoop(iterations: number, callback: ?EndCallback): void {
196196
const singleConfig = {...config, iterations};
197-
start(value, singleConfig);
197+
start(value, singleConfig, callback);
198198
},
199199

200200
_isUsingNativeDriver: function (): boolean {
@@ -246,9 +246,9 @@ const timingImpl = function (
246246
value.resetAnimation();
247247
},
248248

249-
_startNativeLoop: function (iterations?: number): void {
249+
_startNativeLoop(iterations: number, callback: ?EndCallback): void {
250250
const singleConfig = {...config, iterations};
251-
start(value, singleConfig);
251+
start(value, singleConfig, callback);
252252
},
253253

254254
_isUsingNativeDriver: function (): boolean {
@@ -288,9 +288,9 @@ const decayImpl = function (
288288
value.resetAnimation();
289289
},
290290

291-
_startNativeLoop: function (iterations?: number): void {
291+
_startNativeLoop(iterations: number, callback: ?EndCallback): void {
292292
const singleConfig = {...config, iterations};
293-
start(value, singleConfig);
293+
start(value, singleConfig, callback);
294294
},
295295

296296
_isUsingNativeDriver: function (): boolean {
@@ -484,7 +484,7 @@ const loopImpl = function (
484484
callback && callback({finished: true});
485485
} else {
486486
if (animation._isUsingNativeDriver()) {
487-
animation._startNativeLoop(iterations);
487+
animation._startNativeLoop(iterations, callback);
488488
} else {
489489
restart(); // Start looping recursively on the js thread
490490
}

packages/react-native/Libraries/Animated/AnimatedMock.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ export type CompositeAnimation = {
6565
start: (callback?: ?EndCallback) => void,
6666
stop: () => void,
6767
reset: () => void,
68-
_startNativeLoop: (iterations?: number) => void,
68+
_startNativeLoop: (iterations: number, callback: ?EndCallback) => void,
6969
_isUsingNativeDriver: () => boolean,
7070
...
7171
};

packages/react-native/Libraries/Animated/__tests__/Animated-test.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -693,6 +693,31 @@ describe('Animated', () => {
693693
expect(animation.reset).toHaveBeenCalledTimes(1);
694694
expect(cb).toBeCalledWith({finished: false});
695695
});
696+
697+
it('stops looping native animations', () => {
698+
const value = new Animated.Value(0);
699+
const animation = Animated.timing(value, {
700+
toValue: 1,
701+
useNativeDriver: true,
702+
});
703+
704+
jest.spyOn(animation, '_startNativeLoop');
705+
jest.spyOn(animation, 'stop');
706+
707+
const callback = jest.fn();
708+
709+
const loop = Animated.loop(animation);
710+
loop.start(callback);
711+
712+
expect(animation._startNativeLoop).toBeCalledTimes(1);
713+
expect(animation.stop).not.toBeCalled();
714+
expect(callback).not.toBeCalled();
715+
716+
loop.stop();
717+
718+
expect(animation.stop).toBeCalled();
719+
expect(callback).toBeCalledWith({finished: false});
720+
});
696721
});
697722

698723
it('does not reset animation in a loop if resetBeforeIteration is false', () => {

0 commit comments

Comments
 (0)