war.ukraine.ua, vshymanskyy/StandWithUkraine
Hook for progressive image loading, alternative to react-progressive-image.
- Supports
<img>
and<picture>
with<source>
elements. - If image is in browser's cache,
loading
will be immediatellyfalse
in Chrome, Firefox, and Edge. - SSR: Returns
false
on the server, so the server returns image paths instead of placeholders because by the time js is loaded, parsed, and React initialized, most images would have already fully or at least partially loaded. If React is ready and an image is still loading, we have a mismatch andloading
is going to betrue
on the client when that happens. If you want to prevent that, setssr
totrue
. But this option might not work in development if you're using webpack, probably because webpack dev environment is a little bit magical. - Written in TypeScript.
$ npm i @ohs/use-progressive-image
$ yarn add @ohs/use-progressive-image
function useProgressiveImage(arg: {
img?: string | { sizes?: string; src?: string; srcSet?: string; };
sources?: { sizes?: string; src?: string; srcSet?: string; type?: string; media?: string }[];
ssr?: boolean; // set to true if it's an SSR app
// returns `loading` and an `Error` event if failed to load
}): [boolean, Event | string | undefined]
import React, { useMemo } from 'react';
import useProgressiveImage from '@ohs/use-progressive-image';
export interface ImgProps {
lqip?: string;
src?: string;
}
const Img: React.FC<ImgProps> = ({ lqip, src }) => {
const [loading] = useProgressiveImage({ img: src });
return (
<img src={loading ? lqip : src} />
);
};
import React, { useMemo } from 'react';
import useProgressiveImage from '@ohs/use-progressive-image';
export interface ImgProps {
lqip?: string;
src?: string;
avif?: string;
}
const Img: React.FC<ImgProps> = ({ lqip, src, avif }) => {
// It's recommended to memoize `sources` array, otherwise it will be deep
// compared with previous value on each rerender in `useProgressiveImage`
const sources = useMemo(() => [{
srcSet: avif,
type: 'image/avif'
}], [avif]);
const [loading] = useProgressiveImage({ img: src, sources });
return (
<picture>
{!loading && <source {...sources[0]} />}
<img src={loading ? lqip : src} />
</picture>
);
};