diff --git a/packages/lib-classifier/src/hooks/useSubjectImage.js b/packages/lib-classifier/src/hooks/useSubjectImage.js index ffda912dfa..e3ac2a7e74 100644 --- a/packages/lib-classifier/src/hooks/useSubjectImage.js +++ b/packages/lib-classifier/src/hooks/useSubjectImage.js @@ -6,12 +6,14 @@ export default function useSubjectImage({ src, onReady, onError }) { const { img, error, loading } = useProgressiveImage({ placeholderSrc: '', - src + src, + onLoad, + onError }) - useEffect(function onImageLoad() { - const { naturalHeight, naturalWidth, src } = img + function onLoad(event) { + const { naturalHeight, naturalWidth, src } = event.target if (src !== '' ) { const svgImage = subjectImage.current const { width: clientWidth, height: clientHeight } = svgImage @@ -20,14 +22,7 @@ export default function useSubjectImage({ src, onReady, onError }) { const target = { clientHeight, clientWidth, naturalHeight, naturalWidth } onReady({ target }) } - }, [img, onReady, subjectImage]) - - useEffect(function logError() { - if (!loading && error) { - console.error(error) - onError(error) - } - }, [error, loading, onError]) + } return { img, error, loading, subjectImage } } diff --git a/packages/lib-react-components/CHANGELOG.md b/packages/lib-react-components/CHANGELOG.md index 74b649f1d6..56ea1db6eb 100644 --- a/packages/lib-react-components/CHANGELOG.md +++ b/packages/lib-react-components/CHANGELOG.md @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - PlainButton has text-decoration underline on hover even for links. - ZooFooter links and labels updated to reflect newly launched FEM pages. - Updated styling in ProjectCard's badge component. +- `useProgressiveImage`: run `onLoad` callbacks immediately when `delay` is 0. ### Fixed diff --git a/packages/lib-react-components/src/Media/components/ThumbnailImage/ThumbnailImage.spec.js b/packages/lib-react-components/src/Media/components/ThumbnailImage/ThumbnailImage.spec.js index f087ff9a5a..01fcf30f68 100644 --- a/packages/lib-react-components/src/Media/components/ThumbnailImage/ThumbnailImage.spec.js +++ b/packages/lib-react-components/src/Media/components/ThumbnailImage/ThumbnailImage.spec.js @@ -12,7 +12,11 @@ describe('ThumbnailImage', function () { constructor () { this.naturalHeight = 200 this.naturalWidth = 400 - setTimeout(() => this.onload(), 0) + const fakeLoadEvent = { + ...new Event('load'), + target: this + } + setTimeout(() => this.onload(fakeLoadEvent), 0) } } diff --git a/packages/lib-react-components/src/hooks/useProgressiveImage.js b/packages/lib-react-components/src/hooks/useProgressiveImage.js index 5c28d35189..34f0bb0509 100644 --- a/packages/lib-react-components/src/hooks/useProgressiveImage.js +++ b/packages/lib-react-components/src/hooks/useProgressiveImage.js @@ -1,4 +1,4 @@ -import { useEffect, useState } from 'react' +import { useEffect, useRef, useState } from 'react' const defaultPlaceholder = { naturalHeight: 600, @@ -6,35 +6,55 @@ const defaultPlaceholder = { src: '' } +const DEFAULT_HANDLER = () => false + +function preloadImage({ + src, + onLoad = DEFAULT_HANDLER, + onError = DEFAULT_HANDLER +}) { + const { Image } = window + const img = new Image() + img.onload = onLoad + img.onerror = onError + img.src = src +} + export default function useProgressiveImage({ delay = 0, placeholderSrc = '', - src + src, + onLoad = DEFAULT_HANDLER, + onError = DEFAULT_HANDLER }) { const placeholder = { ...defaultPlaceholder, src: placeholderSrc } const [loading, setLoading] = useState(true) - const [img, setImg] = useState(placeholder) + const imgRef = useRef(placeholder) const [error, setError] = useState(null) + function onImageLoad(event) { + imgRef.current = event.target + onLoad(event) + setLoading(false) + } + + function onImageError(error) { + onError(error) + setError(error) + setLoading(false) + } + function fetchImage() { - const { Image } = window - const img = new Image() - img.onload = () => { - setTimeout(() => { - setImg(img) - setLoading(false) - }, delay) - } - img.onerror = (error) => { - setError(error) - setLoading(false) - } setLoading(true) setError(null) - img.src = src + preloadImage({ + src, + onLoad: delay ? event => setTimeout(onImageLoad, delay, event) : onImageLoad, + onError: onImageError + }) } useEffect(function onNewImage() { @@ -43,5 +63,5 @@ export default function useProgressiveImage({ } }, [src]) - return { img, error, loading } + return { img: imgRef.current, error, loading } }