@@ -4,28 +4,39 @@ import { useEffect, type RefObject } from 'react';
44 * Flag images that fail to load so CSS can swap in a broken-image placeholder.
55 */
66export const useImageErrorFallback = (
7- containerRef : RefObject < HTMLElement | null > ,
8- html : string
7+ containerRef : RefObject < HTMLElement | null >
98) => {
9+ // listen for errors
1010 useEffect ( ( ) => {
1111 const container = containerRef . current ;
1212 if ( ! container ) return ;
1313
14- const images = container . querySelectorAll < HTMLImageElement > ( 'img' ) ;
15- const cleanups : ( ( ) => void ) [ ] = [ ] ;
14+ const handleImageError = ( e : Event ) => {
15+ const target = e . target as HTMLElement ;
16+ if ( target && target . tagName && target . tagName . toLowerCase ( ) === 'img' ) {
17+ target . classList . add ( 'error' ) ;
18+ }
19+ } ;
1620
17- images . forEach ( ( img ) => {
18- const handleImageError = ( ) => img . classList . add ( 'error' ) ;
21+ container . addEventListener ( 'error' , handleImageError , true ) ;
1922
20- img . addEventListener ( 'error' , handleImageError ) ;
21- cleanups . push ( ( ) => img . removeEventListener ( 'error' , handleImageError ) ) ;
23+ return ( ) => {
24+ container . removeEventListener ( 'error' , handleImageError , true ) ;
25+ } ;
26+ } , [ containerRef ] ) ;
2227
23- // Catch images that already failed before the listener attached
28+ // handle the cached unloaded images that will not emit the error event
29+ useEffect ( ( ) => {
30+ const container = containerRef . current ;
31+ if ( ! container ) return ;
32+
33+ const images =
34+ container . querySelectorAll < HTMLImageElement > ( 'img:not(.error)' ) ;
35+
36+ images . forEach ( ( img ) => {
2437 if ( img . complete && img . naturalHeight === 0 ) {
25- handleImageError ( ) ;
38+ img . classList . add ( 'error' ) ;
2639 }
2740 } ) ;
28-
29- return ( ) => cleanups . forEach ( ( cleanup ) => cleanup ( ) ) ;
30- } , [ containerRef , html ] ) ;
41+ } ) ;
3142} ;
0 commit comments