From 252fc101f5cf0f1d3e426a6b616553347f3a7791 Mon Sep 17 00:00:00 2001 From: Krzysztof Moch Date: Mon, 4 Aug 2025 16:56:03 +0200 Subject: [PATCH 1/2] fix: clear state in `useImage` hook --- packages/react-native-nitro-image/src/useImage.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/react-native-nitro-image/src/useImage.ts b/packages/react-native-nitro-image/src/useImage.ts index 0030397a..be48eaa8 100644 --- a/packages/react-native-nitro-image/src/useImage.ts +++ b/packages/react-native-nitro-image/src/useImage.ts @@ -37,6 +37,11 @@ export function useImage(source: AsyncImageSource): Result { // biome-ignore lint: The dependencies array is a bit hacky. useEffect(() => { + // clear state each time we will load a new image + if (image.image || image.error) { + setImage({ image: undefined, error: undefined }); + } + (async () => { try { // 1. Create the Image/ImageLoader instance From cfbd545304062eb03dc81fa9c115e7b2d3965ef4 Mon Sep 17 00:00:00 2001 From: Krzysztof Moch Date: Wed, 1 Oct 2025 23:27:35 +0200 Subject: [PATCH 2/2] perf: check if we should clear state --- .../react-native-nitro-image/src/useImage.ts | 29 +++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/packages/react-native-nitro-image/src/useImage.ts b/packages/react-native-nitro-image/src/useImage.ts index be48eaa8..e08244f5 100644 --- a/packages/react-native-nitro-image/src/useImage.ts +++ b/packages/react-native-nitro-image/src/useImage.ts @@ -21,6 +21,32 @@ type Result = error: Error; }; +const isSameSource = (a: AsyncImageSource, b: AsyncImageSource) => { + if (!b) return false; + + if (isHybridObject(a) && isHybridObject(b)) { + return a.equals(b); + } + + return JSON.stringify(a) === JSON.stringify(b); +}; + +const shouldClearState = (source: AsyncImageSource, result: Result) => { + const { image, error } = result; + + // If there was an error, we need to clear the state + if (error) return true; + + // If there is an image, we check if the source has changed + // if not, we don't need to clear the state + if (image && "__source" in image && image.__source) { + // @ts-expect-error - We save the source on the JS side so we can diff it + return !isSameSource(source, image.__source); + } + + return false; +}; + /** * A hook to asynchronously load an image from the * given {@linkcode AsyncImageSource} into memory. @@ -37,8 +63,7 @@ export function useImage(source: AsyncImageSource): Result { // biome-ignore lint: The dependencies array is a bit hacky. useEffect(() => { - // clear state each time we will load a new image - if (image.image || image.error) { + if (shouldClearState(source, image)) { setImage({ image: undefined, error: undefined }); }