it-source

React.js에서 이미지를 프리로드하는 방법

criticalcode 2023. 3. 7. 21:33
반응형

React.js에서 이미지를 프리로드하는 방법

React.js에서 이미지를 프리로드하는 방법메뉴와 같이 동작하는 드롭다운 선택 컴포넌트가 있습니다만, 처음에 열었을 때 보이지 않을 수 있기 때문에 아이템의 이미지 아이콘을 미리 로드해야 합니다.

시도했습니다.

https://github.com/sambernard/react-preload

https://github.com/wizardzloy/react-img-preload

첫 번째는 이해하기 쉽고 사용하기 쉬운 API를 갖추고 있지만 이미지가 로드되어도 로드되지 않았다는 경고를 표시하는 Spaming Console입니다.두 번째는 이상한 API를 가지고 있는데 예를 들어봤는데 아무것도 프리로드 되지 않았습니다.

그래서 아마 저 스스로 무언가를 구현해야 할 것 같습니다만, 어디서부터 시작해야 할지 모르겠습니다.또는 웹 팩을 로드하는 방법도 있습니다.

pictures: string[]; URL 배열 컴' 、 컴 - 、 URL 。 정의해야 .componentDidMount()컴포넌트 내의 메서드를 작성한 후 새로 만들기Image"CHANGE: "CHANGE: "CHANGE:

componentDidMount() {
    this.props.pictures.forEach((picture) => {
        const img = new Image();
        img.src = picture.fileName;
    });
}

브라우저가 모든 이미지를 강제로 로드합니다.

은 리액트입니다(「」를 사용).TypeScript컴포넌트 내부에 이미지를 프리로드하는 방법.후크로도 만들 수 있어요.

에서는 '이렇게'를 사용하고 .useEffect ★★★★★★★★★★★★★★★★★」useState여기입니다만, 실제 프리 로딩 작업은,preloadImage()기능을 가지고 있습니다.수입하다

구성 요소 내부에 직접 추가

import React, { useEffect, useState } from 'react'

import Image1 from 'images/image1.png'
import Image2 from 'images/image2.jpg'
import Image3 from 'images/image3.svg'

const preloadSrcList: string[] = [
  Image1,
  Image2,
  Image3,
]

function preloadImage (src: string) {
  return new Promise((resolve, reject) => {
    const img = new Image()
    img.onload = function() {
      resolve(img)
    }
    img.onerror = img.onabort = function() {
      reject(src)
    }
    img.src = src
  })
}

export default function Component() {
  const [assetsLoaded, setAssetsLoaded] = useState<boolean>(false)

  useEffect(() => {
    let isCancelled = false

    async function effect() {
      if (isCancelled) {
        return
      }

      const imagesPromiseList: Promise<any>[] = []
      for (const i of preloadSrcList) {
        imagesPromiseList.push(preloadImage(i))
      }
  
      await Promise.all(imagesPromiseList)

      if (isCancelled) {
        return
      }

      setAssetsLoaded(true)
    }

    effect()

    return () => {
      isCancelled = true
    }
  }, [])

  if (!assetsLoaded) {
    return <p>Preloading Assets</p>
  }

  return <p>Assets Finished Preloading</p>
}

후크로서 최적: use Image Preloader()

import { useEffect, useState } from 'react'

function preloadImage (src: string) {
  return new Promise((resolve, reject) => {
    const img = new Image()
    img.onload = function() {
      resolve(img)
    }
    img.onerror = img.onabort = function() {
      reject(src)
    }
    img.src = src
  })
}

export default function useImagePreloader(imageList: string[]) {
  const [imagesPreloaded, setImagesPreloaded] = useState<boolean>(false)

  useEffect(() => {
    let isCancelled = false

    async function effect() {
      console.log('PRELOAD')

      if (isCancelled) {
        return
      }

      const imagesPromiseList: Promise<any>[] = []
      for (const i of imageList) {
        imagesPromiseList.push(preloadImage(i))
      }
  
      await Promise.all(imagesPromiseList)

      if (isCancelled) {
        return
      }

      setImagesPreloaded(true)
    }

    effect()

    return () => {
      isCancelled = true
    }
  }, [imageList])

  return { imagesPreloaded }
}

컴포넌트 내에서 useImagePreloader() 사용

import React, { useEffect, useState } from 'react'
import useImagePreloader from 'hooks/useImagePreloader'

import Image1 from 'images/image1.png'
import Image2 from 'images/image2.jpg'
import Image3 from 'images/image3.svg'

const preloadSrcList: string[] = [
  Image1,
  Image2,
  Image3,
]

export default function Component() {
  const { imagesPreloaded } = useImagePreloader(preloadSrcList)

  if (!imagesPreloaded) {
    return <p>Preloading Assets</p>
  }

  return <p>Assets Finished Preloading</p>
}

이 되지 경우 를 .windowobject :

componentDidMount() {
    const imagesPreload = [image1, image2, image3];
    imagesPreload.forEach((image) => {
        const newImage = new Image();
        newImage.src = image;
        window[image] = newImage;
    });
}

window (오브젝트)

리액션 훅 방식

useEffect(() => {
  //preloading image
  faceArray.forEach((face) => {
    const img = new Image();
    img.src = face;
  });
}, []);

이 방법은 다음과 같습니다.

import im1 from 'img/im1.png'
import im2 from 'img/im2.png'
import im3 from 'img/im3.png'

componentDidMount() {
    imageList = [im1, im2, im3]
    imageList.forEach((image) => {
        new Image().src = image
    });
}

이 기능을 모든 기능 컴포넌트에서 사용할 수 있는 커스텀훅에 넣는 방법을 다음에 나타냅니다.

일부 답변이 누락된 중요한 부분은 미리 로드된 이미지에 대한 참조를 창 개체와 같은 곳에 저장하는 것입니다.이렇게 하지 않으면 이미 이미지가 미리 로드되어 있음에도 불구하고 브라우저가 실제로 필요한 이미지를 다시 요구할 수 있습니다.

훅을 할 때 가 훅에 됩니다.window라고 하는usePreloadImagesData 기izedizedizedizedizedizedizedizedizedized로 초기화 됩니다.{}.

컴포넌트에 키가 됩니다.window.usePreloadImagesData 으로 생성됩니다. 키의 이름은 임의로 생성됩니다.되어 있습니다.[].

후크는 이미지 소스 문자열 배열을 사용합니다.소스에 , 「」를 해 주세요.new Image()되어 있습니다.window.usePreloadImagesData[randomStr]manager.manager로 하다

배열이 되면 " " "는 " " " 입니다.window.usePreloadImagesData[randomStr]메모리 누수를 방지하기 위해 이 삭제됩니다.

이 예는 Typescript에 기재되어 있습니다.

import { useEffect } from 'react';

declare global {
  interface Window {
    usePreloadImagesData?: Record<string, unknown[]>;
  }
}

export const usePreloadImages = (imageSrcs: string[]): void => {
  useEffect(() => {
    const randomStr = Math.random().toString(32).slice(2) + Date.now();
    window.usePreloadImagesData = window.usePreloadImagesData ?? {};
    window.usePreloadImagesData[randomStr] = [];
    for (const src of imageSrcs) {
      // preload the image
      const img = new Image();
      img.src = src;
      // keep a reference to the image
      window.usePreloadImagesData[randomStr].push(img); 
    }
    return () => {
      delete window.usePreloadImagesData?.[randomStr];
    };
  }, [ imageSrcs ]);
};

이 후크를 사용할 때는 후크에 전달되는 이미지 소스 문자열 배열이 일정하게 유지되는지 확인하십시오. 하거나 ,, or, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, like, like, like, like, like 사용합니다.React.useMemo.

예.

import React from 'react';
import { usePreloadImages } from '../hooks/usePreloadImages';

import img1 from './image-1.jpg';
import img2 from './image-2.jpg';

const preload = [ img1, img2 ]; // create constant array here, outside the component

export const MyComponent: React.FC = () => {

  usePreloadImages(preload); // correct
  // usePreloadImages([ img1, img2 ]); // incorrect

  return (
    // ...
  );
};

몇 개의 작은 "아이콘" (글꼴을 사용하지 않는 이유)만 전달하고 서버가 gzipped 파일을 제공하는 경우 base64를 사용할 수 있습니다.

않으면 추가할 .display: none이전 HTML에 또 다른 하고 를 기다리는 입니다.DOM.onload컴포넌트를 표시하기 전에 (이 접근법은 말씀하신 라이브러리에서 사용됩니다)

웹 팩이나 리액션은 여기서 특별한 일을 해줄 수 없습니다.이것은 클라이언트측의 것으로, 독자적인 프리로드 API(또는 JS/TS, React, Angular 등의 기존 API 사용)를 실장하기 위한 툴에 지나지 않습니다.

음, 친구여, 링크 릴 프리로드 / 프리페치 및 webpack lazy loading chunks 옵션이 몇 가지 있습니다.

상세 정보:

https://github.com/GoogleChromeLabs/preload-webpack-plugin

단일 구성 요소 내에서만 이미지를 사전 로드해야 하는 경우:

const preloadedSpinner = useRef();

useEffect(() => {
    preloadedSpinner.current = new Image();
    preloadedSpinner.current.src = "my/image/source";
}, []);

을 src로 할 수 .display: none자신의 상태에 따라 이미지가 나타나도록 스타일링을 삭제하기만 하면 됩니다.이렇게 하면 이미지가 미리 로드되지만 필요할 때까지 표시되지 않습니다.하다

<SliderItem
    style={slideIndex === 1 ? null : { display: 'none' }}
    src={imgSrc}
    alt={'Kitchen furniture'}
    text={'Caption Text'}
    textStyle={classes.text}
    MySlides={classes.MySlides}
  />
  <SliderItem
    style={slideIndex === 2 ? null : { display: 'none' }}
    src={'/bedroom.jpg'}
    alt={'Bedroom furniture'}
    text={'Caption Text'}
    textStyle={classes.text}
    MySlides={classes.MySlides}
  />
  <SliderItem
    style={slideIndex === 3 ? null : { display: 'none' }}
    src={'/living-room.jpg'}
    alt={'Living-room furniture'}
    text={'Caption Text'}
    textStyle={classes.text}
    MySlides={classes.MySlides}
  />

다음의 커스텀 훅을 사용할 수 있습니다.

import { useEffect, useState } from 'react';

const preloadImage = (src: string): Promise<HTMLImageElement> =>
  new Promise((resolve, reject) => {
    const img = new Image();

    img.onload = () => resolve(img);
    img.onerror = img.onabort = () => reject();
    img.src = src;
  });

const useImagePreloader = (imageList: string[]) => {
  const [imagesPreloaded, setImagesPreloaded] = useState(false);

  useEffect(() => {
    let isCancelled = false;

    const preloadImages = async () => {
      const imagesPromiseList: Promise<HTMLImageElement>[] =  imageList.map((img) =>
        preloadImage(img),
      );

      try {
        await Promise.all(imagesPromiseList);
      } catch (error: unknown) {
        console.error(error);
      }

      if (isCancelled) {
        return;
      }

      setImagesPreloaded(true);
    };

    preloadImages();

    return () => {
      isCancelled = true;
    };
  }, [imageList]);

  return { imagesPreloaded };
};

export default useImagePreloader;

리액트 서스펜스를 사용하여 이미지를 프리로드 할 수 있습니다!

몇 가지 이미지를 미리 로드합니다.

  • 내 경우 내 이미지에 대한 초기 src 속성으로 시작하고 브라우저에 이미지가 로드된 후 이미지 변경을 지연시키고자 합니다.
import { useEffect, useState } from 'react';

export const useImageLoader = (initialSrc: string, currentSrc: string) => {
  const [imageSrc, _setImageSrc] = useState(initialSrc);

  useEffect(() => {
    const img = new Image();
    img.onload = () => {
      _setImageSrc(currentSrc);
    };
    img.src = currentSrc;
  }, [currentSrc]);

  return [imageSrc];
};

리액트용

    import imageToScroll ...
    const [imageIsLoaded, setImageIsLoaded] = useState(false);
    useEffect(() => {
            let img = new Image();
            img.src = image.imageToScroll;
        }, [imageIsLoaded])
    <img src={image.imageToScroll}
        onLoad={() => setImageIsLoaded(true)}
    />

예를 들어,images각 이미지에 대한 데이터를 포함하는 배열로, 한 줄에서 수행할 수 있습니다.

componentDidMount() {
  this.props.images.forEach(image => (new Image().src = image.src));
}

이것은 매우 늦은 답변입니다.React Fluent UI 컴포넌트의 드롭다운 이미지를 렌더링하는 것과 같은 문제가 있었습니다.해결방법은 파일 확장자를 .png에서 .jpg로 변경하고 확장자도 계속 업데이트하는 것이었습니다.바로 그거야!

언급URL : https://stackoverflow.com/questions/42615556/how-to-preload-images-in-react-js

반응형