prevent images from blinking when src updates

This commit is contained in:
jeffvli
2026-07-17 02:18:45 -07:00
parent f17ab42ac2
commit 0940a4d1f5
@@ -25,6 +25,7 @@ export function useNativeImage({
const abortControllerRef = useRef<AbortController | null>(null);
const loadedRequestSignatureRef = useRef<null | string>(null);
const objectUrlRef = useRef<null | string>(null);
const retiredObjectUrlsRef = useRef<string[]>([]);
const onFetchErrorRef = useRef(onFetchError);
const [state, setState] = useState<NativeImageState>({ status: 'idle' });
@@ -82,8 +83,10 @@ export function useNativeImage({
}
abortCurrentRequest();
revokeObjectUrl();
setState({ status: 'loading' });
setState((currentState) => ({
displaySrc: currentState.displaySrc,
status: 'loading',
}));
const abortController = new AbortController();
abortControllerRef.current = abortController;
@@ -113,6 +116,9 @@ export function useNativeImage({
}
const objectUrl = URL.createObjectURL(blob);
if (objectUrlRef.current) {
retiredObjectUrlsRef.current.push(objectUrlRef.current);
}
objectUrlRef.current = objectUrl;
loadedRequestSignatureRef.current = requestSignature;
setState({ displaySrc: objectUrl, status: 'loaded' });
@@ -140,6 +146,11 @@ export function useNativeImage({
};
}, [enabled, fetchPriority, request, requestSignature]);
useEffect(() => {
retiredObjectUrlsRef.current.forEach((objectUrl) => URL.revokeObjectURL(objectUrl));
retiredObjectUrlsRef.current = [];
}, [state.displaySrc]);
useEffect(() => {
return () => {
abortControllerRef.current?.abort();
@@ -147,6 +158,8 @@ export function useNativeImage({
if (objectUrlRef.current) {
URL.revokeObjectURL(objectUrlRef.current);
}
retiredObjectUrlsRef.current.forEach((objectUrl) => URL.revokeObjectURL(objectUrl));
};
}, []);