web-dev-qa-db-ja.com

React JSコンポーネントに画像をプリロードする方法は?

現在、signInErrorが発生したときに子コンポーネントをレンダリングしています。 signInErrorは親コンポーネントに格納され、nullでない場合、以下のコードに従って_<SignInError/>_コンポーネントをレンダリングします。

ParentComponent.js

_  // Some code...

  render() {
    return(
      <div>
        <SignInForm
          doSignIn={this.doSignIn}
          resetSignInError={this.resetSignInError}
          signInError={this.state.signInError}
        />
        {this.state.signInError && <SignInError/>}
      </div>
    );
  }
_

これまでのところ、とても良い、これが子コンポーネント_SignInError.js_です

_import React from 'react';
import RoundImage from '../../../UI/Common/RoundImage';
import Newman from '../../../../assets/newman-min.png';

class SignInError extends React.Component {
  constructor(props){
    super(props);
  }

    componentDidMount(){
    const img = new Image();
    img.src = Newman;
  }

  render(){
    return(
      <div>
      <div>
        <RoundImage src={img.src}/> // <--- img is undefined here!!!
      </div>
      <div>
        Hello... Newman!
      </div>
    </div>
    );
  }
}

export default SignInError;
_

RoundImage.js

_import React from 'react';

const RoundImage = (props) => {
  return (
    <div>
      <img src={props.src}/>
    </div>
  );
}

export default RoundImage;
_

React.jsに画像をプリロードする方法

スタックオーバーフローに関するこの質問の回答(上記のリンク)は、componentDidMount()メソッド内にimgオブジェクトを作成してブラウザーに強制的にロードするように指示しています。上記のコードからわかるように、そうしました。しかし今、それをrenderメソッド内の孫コンポーネントにプロップとして渡そうとすると、imgにアクセスできません。これは、別のメソッド内で定義されているためです。

これを回避する最良の方法は何ですか?画像を読み込んで、エラーメッセージと共に表示するだけです。それ以外の場合、ブラウザが画像をまだキャッシュしていない場合は、エラーメッセージが画像の前に表示されます。助けてくれてありがとう。

3
cbdeveloper

画像のダウンロードはブラウザで行われます。 DOMへのレンダリングはブラウザでも行われます。

preloadingとは、画像の準備ができたときにのみコンポーネントがレンダリングすることを意味しますか?

もしそうなら、あなたはこのようなことをすることができます:

componentDidMount() {
  const img = new Image();
  img.src = Newman; // by setting an src, you trigger browser download

  img.onload = () => {
    // when it finishes loading, update the component state
    this.setState({ imageIsReady: true });
  }
}

render() {
  const { imageIsReady } = this.state;

  if (!imageIsReady) {
    return <div>Loading image...</div>; // or just return null if you want nothing to be rendered.
  } else {
    return <img src={Newman} /> // along with your error message here
  }
}
5
Jackyef

少し異なるアプローチですが、事前にイメージソースがある場合は、プリロードオプションを使用して、イメージソースをメインHTMLファイルにリンク参照として追加できます。ブラウザーは画像を(比較的低い優先順位で)プリロードし、アプリが画像をロードするときに、ブラウザーのメモリにキャッシュする必要があります。

<head>
..
..
<link rel="preload" href="<your_image_source_here>" as="image">
...
</head>

このアプローチでは、プリロードプロセスをコードから分離します。事前に(動的ではなく)画像ソースがある場合、および大量の画像をキャッシュする必要がない場合(HTMLヘッドに大量のリンクリストを追加するのは少し面倒ですが、可能)

リンクのプリロードについて詳しくは、こちらをご覧ください。 rel = "preload"を使用したコンテンツのプリロード

1
Dan Porat