Image.tsx 1.4 KB
Newer Older
1 2
import React, {FunctionComponent, useEffect, useState, useRef} from 'react';
import fetch from 'isomorphic-unfetch';
P
Peter Pan 已提交
3
import {useTranslation} from '~/utils/i18n';
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44

type ImageProps = {
    src?: string;
};

const Image: FunctionComponent<ImageProps> = ({src}) => {
    const {t} = useTranslation('common');

    const [url, setUrl] = useState('');
    const [loading, setLoading] = useState(false);

    const controller = useRef(null as AbortController | null);

    useEffect(() => {
        if (process.browser) {
            let objectUrl: string | null = null;
            (async () => {
                setLoading(true);
                controller.current?.abort();
                controller.current = new AbortController();
                try {
                    const result = await fetch(src ?? '', {signal: controller.current.signal});
                    const blob = await result.blob();
                    objectUrl = URL.createObjectURL(blob);
                    setUrl(objectUrl);
                } catch {
                    // ignore abort error
                } finally {
                    setLoading(false);
                }
            })();
            return () => {
                objectUrl && URL.revokeObjectURL(objectUrl);
            };
        }
    }, [src]);

    return loading ? <span>{t('loading')}</span> : <img src={url} />;
};

export default Image;