import react, { useEffect, useRef } from 'react'; export interface TileProperties { /** The image's source URL */ href: string; /** Its size */ size: number; /** A delay to add (for test/debug purposes) */ delay?: number; } /** * * @param props * @returns A tile * * Tile components are containers for images. * They return an empty element immediately so that the rendering can proceed * and append a, element whenever the image is loaded. */ export const Tile: react.FC = (props: TileProperties) => { const g = useRef(null); const timeout = (ms: number) => { return new Promise((resolve) => setTimeout(resolve, ms)); }; useEffect(() => { const loadImage = async () => { console.log(`Pre loading: ${props.href}`); const image = new Image(props.size, props.size); image.loading = 'eager'; // @ts-ignore image.setAttribute('href', props.href); if (!image.complete) { await image.decode(); } if (props.delay !== undefined) { await timeout(props.delay); } const svgImage = document.createElementNS( 'http://www.w3.org/2000/svg', 'image' ) as unknown as SVGImageElement; svgImage.setAttribute('width', props.size.toString()); svgImage.setAttribute('height', props.size.toString()); // @ts-ignore svgImage.setAttribute('href', props.href); g.current?.replaceChildren(svgImage); }; loadImage(); }, [props.href, props.size]); return ; }; export default Tile;