From 7584051ff18e96a627ca8f1183532d446d543b0a Mon Sep 17 00:00:00 2001 From: Jarvis Luong <21980965+jarvisluong@users.noreply.github.com> Date: Fri, 26 Jan 2024 20:37:17 +0200 Subject: [PATCH] Fix useAnimatedImageValue lifecycle (#2172) --- .../reanimated/useAnimatedImageValue.ts | 19 +++++++++++++++---- package/src/skia/core/AnimatedImage.ts | 5 +++-- package/src/skia/core/Data.ts | 12 ++++++++---- 3 files changed, 26 insertions(+), 10 deletions(-) diff --git a/package/src/external/reanimated/useAnimatedImageValue.ts b/package/src/external/reanimated/useAnimatedImageValue.ts index 85e935adfd..736ef4cda6 100644 --- a/package/src/external/reanimated/useAnimatedImageValue.ts +++ b/package/src/external/reanimated/useAnimatedImageValue.ts @@ -1,3 +1,4 @@ +import { useEffect } from "react"; import type { FrameInfo } from "react-native-reanimated"; import { useAnimatedImage } from "../../skia/core/AnimatedImage"; @@ -15,10 +16,14 @@ export const useAnimatedImageValue = (source: DataSourceParam) => { throwOnMissingReanimated(); const currentFrame = useSharedValue(null); const lastTimestamp = useSharedValue(0); - const animatedImage = useAnimatedImage(source, (err) => { - console.error(err); - throw new Error(`Could not load animated image - got '${err.message}'`); - }); + const animatedImage = useAnimatedImage( + source, + (err) => { + console.error(err); + throw new Error(`Could not load animated image - got '${err.message}'`); + }, + false + ); const frameDuration = animatedImage?.currentFrameDuration() || DEFAULT_FRAME_DURATION; @@ -47,5 +52,11 @@ export const useAnimatedImageValue = (source: DataSourceParam) => { lastTimestamp.value = timestamp; // eslint-disable-next-line react-hooks/exhaustive-deps }, true); + useEffect(() => { + return () => { + animatedImage?.dispose(); + }; + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); return currentFrame; }; diff --git a/package/src/skia/core/AnimatedImage.ts b/package/src/skia/core/AnimatedImage.ts index a49a63ee85..e2f4661d8a 100644 --- a/package/src/skia/core/AnimatedImage.ts +++ b/package/src/skia/core/AnimatedImage.ts @@ -12,5 +12,6 @@ const animatedImgFactory = Skia.AnimatedImage.MakeAnimatedImageFromEncoded.bind( * */ export const useAnimatedImage = ( source: DataSourceParam, - onError?: (err: Error) => void -) => useRawData(source, animatedImgFactory, onError); + onError?: (err: Error) => void, + managed = true +) => useRawData(source, animatedImgFactory, onError, managed); diff --git a/package/src/skia/core/Data.ts b/package/src/skia/core/Data.ts index 264d4a0c90..c694bff542 100644 --- a/package/src/skia/core/Data.ts +++ b/package/src/skia/core/Data.ts @@ -40,7 +40,8 @@ export const loadData = ( const useLoading = >( source: DataSourceParam, - loader: () => Promise + loader: () => Promise, + manage = true ) => { const mounted = useRef(false); const [data, setData] = useState(null); @@ -54,7 +55,9 @@ const useLoading = >( } }); return () => { - dataRef.current?.dispose(); + if (manage) { + dataRef.current?.dispose(); + } mounted.current = false; }; // eslint-disable-next-line react-hooks/exhaustive-deps @@ -94,8 +97,9 @@ export const useCollectionLoading = >( export const useRawData = >( source: DataSourceParam, factory: (data: SkData) => T | null, - onError?: (err: Error) => void -) => useLoading(source, () => loadData(source, factory, onError)); + onError?: (err: Error) => void, + manage = true +) => useLoading(source, () => loadData(source, factory, onError), manage); const identity = (data: SkData) => data;