Reactで画像をプリロードする方法


React で 画像をプリロードする方法

環境
- react v16.8.6

Reactで画像を扱う際に、プリロードしてスムーズな表示をする方法を調べました。

画像をプリロードする

jsx に描画する前に、Imageオブジェクトを予め生成します

const img = new Image()

生成した Imageオブジェクト に画像へのパスを渡します。
渡した時点で Imageオブジェクトはプリロードを始めます!

const src = "public/assets/sample.jpg"
img.src = src // ここでプリロードが始まる

onload にコールバックを渡して、読み込みが終わったら描画をするようにもできます。

img.onload = () => { // 読み込み完了時に発火する関数
    this.setState({ preload: true }) // 例えばこんな風に
}

ビフォーアフター

プリロードした場合としない場合で、どのような違いがあるのかを見てみましょう。
ボタンを押したら画像が表示されるようなコンポーネントを作成しました。
画像はunsplashから重そうなものを選びました。

ビフォー

import React, { Component } from 'react';

const imgPath = 'https://images.unsplash.com/photo-1444703686981-a3abbc4d4fe3?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=2550&q=80'
class App extends Component {
  constructor(props) {
    super(props)
    this.state = {
      show: false
    }
    // const img = new Image()
    // img.src = imgPath
  }

  render () {
    const { show } = this.state
    if (show) {
      return (
        <div>
          <img style={{ width: '100%', height: '100%'}} src={imgPath} alt='sample image' />
        </div>
      )
    }
    else {
      return (
        <div>
          <button type="button" onClick={() => this.setState({ show: true })} >show image</button>
        </div>
      )
    }
  }
}

ボタンを押すと画像の読み込みが始まります。

読み込まれるまで真っ白な画面が表示されます。

アフター

import React, { Component } from 'react';

const imgPath = 'https://images.unsplash.com/photo-1444703686981-a3abbc4d4fe3?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=2550&q=80'
class App extends Component {
  constructor(props) {
    super(props)
    this.state = {
      show: false
    }
    const img = new Image()
    img.src = imgPath // プリロードする
  }

  render () {
    const { show } = this.state
    if (show) {
      return (
        <div>
          <img style={{ width: '100%', height: '100%'}} src={imgPath} alt='sample image' />
        </div>
      )
    }
    else {
      return (
        <div>
          <button type="button" onClick={() => this.setState({ show: true })} >show image</button>
        </div>
      )
    }
  }
}

描画する前から読み込まれています。

キャッシュを利用するので、素早く描画することができます。

以上です。
もっと良い方法があれば、ご教授お願いしますmm