mirror of
https://github.com/nextui-org/nextui.git
synced 2025-12-08 19:26:11 +00:00
fix(use-image): load images after props change (#4523)
* fix(use-image): load image after props change * chore(changeset): add changeset * refactor(use-image): remove unused props * feat(use-image): add test case * fix(use-image): apply useCallback to load & remove status check * chore(changeset): update package name
This commit is contained in:
parent
8452603b5b
commit
f9c2be4509
5
.changeset/light-peaches-reflect.md
Normal file
5
.changeset/light-peaches-reflect.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"@heroui/use-image": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
fix loading image after props changes (#4518)
|
||||||
@ -27,6 +27,19 @@ describe("use-image hook", () => {
|
|||||||
await waitFor(() => expect(result.current).toBe("loaded"));
|
await waitFor(() => expect(result.current).toBe("loaded"));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("can handle changing image", async () => {
|
||||||
|
const {result, rerender} = renderHook(() => useImage({src: undefined}));
|
||||||
|
|
||||||
|
expect(result.current).toEqual("pending");
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
rerender({src: "/test.png"});
|
||||||
|
}, 3000);
|
||||||
|
|
||||||
|
mockImage.simulate("loaded");
|
||||||
|
await waitFor(() => expect(result.current).toBe("loaded"));
|
||||||
|
});
|
||||||
|
|
||||||
it("can handle error image", async () => {
|
it("can handle error image", async () => {
|
||||||
mockImage.simulate("error");
|
mockImage.simulate("error");
|
||||||
const {result} = renderHook(() => useImage({src: "/test.png"}));
|
const {result} = renderHook(() => useImage({src: "/test.png"}));
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
import type {ImgHTMLAttributes, SyntheticEvent} from "react";
|
import type {ImgHTMLAttributes, SyntheticEvent} from "react";
|
||||||
|
|
||||||
import {useRef, useState, useEffect, MutableRefObject} from "react";
|
import {useRef, useState, useEffect, useCallback} from "react";
|
||||||
import {useIsHydrated} from "@heroui/react-utils";
|
import {useIsHydrated} from "@heroui/react-utils";
|
||||||
import {useSafeLayoutEffect} from "@heroui/use-safe-layout-effect";
|
import {useSafeLayoutEffect} from "@heroui/use-safe-layout-effect";
|
||||||
|
|
||||||
@ -66,7 +66,7 @@ type ImageEvent = SyntheticEvent<HTMLImageElement, Event>;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
export function useImage(props: UseImageProps = {}) {
|
export function useImage(props: UseImageProps = {}) {
|
||||||
const {onLoad, onError, ignoreFallback} = props;
|
const {onLoad, onError, ignoreFallback, src, crossOrigin, srcSet, sizes, loading} = props;
|
||||||
|
|
||||||
const isHydrated = useIsHydrated();
|
const isHydrated = useIsHydrated();
|
||||||
|
|
||||||
@ -96,25 +96,7 @@ export function useImage(props: UseImageProps = {}) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
useSafeLayoutEffect(() => {
|
const load = useCallback((): Status => {
|
||||||
if (isHydrated) {
|
|
||||||
setStatus(setImageAndGetInitialStatus(props, imageRef));
|
|
||||||
}
|
|
||||||
}, [isHydrated]);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If user opts out of the fallback/placeholder
|
|
||||||
* logic, let's just return 'loaded'
|
|
||||||
*/
|
|
||||||
return ignoreFallback ? "loaded" : status;
|
|
||||||
}
|
|
||||||
|
|
||||||
function setImageAndGetInitialStatus(
|
|
||||||
props: UseImageProps,
|
|
||||||
imageRef: MutableRefObject<HTMLImageElement | null | undefined>,
|
|
||||||
): Status {
|
|
||||||
const {loading, src, srcSet, crossOrigin, sizes, ignoreFallback} = props;
|
|
||||||
|
|
||||||
if (!src) return "pending";
|
if (!src) return "pending";
|
||||||
if (ignoreFallback) return "loaded";
|
if (ignoreFallback) return "loaded";
|
||||||
|
|
||||||
@ -132,6 +114,19 @@ function setImageAndGetInitialStatus(
|
|||||||
}
|
}
|
||||||
|
|
||||||
return "loading";
|
return "loading";
|
||||||
|
}, [src, crossOrigin, srcSet, sizes, onLoad, onError, loading]);
|
||||||
|
|
||||||
|
useSafeLayoutEffect(() => {
|
||||||
|
if (isHydrated) {
|
||||||
|
setStatus(load());
|
||||||
|
}
|
||||||
|
}, [isHydrated, load]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If user opts out of the fallback/placeholder
|
||||||
|
* logic, let's just return 'loaded'
|
||||||
|
*/
|
||||||
|
return ignoreFallback ? "loaded" : status;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const shouldShowFallbackImage = (status: Status, fallbackStrategy: FallbackStrategy) =>
|
export const shouldShowFallbackImage = (status: Status, fallbackStrategy: FallbackStrategy) =>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user