同形のレンダリングされたページでは、メインのscript.js
ファイルの前に画像をダウンロードできます。したがって、イメージはreact
register onLoad
イベントの前にすでにロードされている可能性があります-このイベントをトリガーしないでください。
script.js
constructor(props) {
super(props);
this.handleImageLoaded = this.handleImageLoaded.bind(this);
}
handleImageLoaded() {
console.log('image loaded');
}
render() {
return (
<img src='image.jpg' onLoad={this.handleImageLoaded} />
);
}
image.jpg
がscript.js
より大きいこのシナリオでは、すべてが正常に機能しています。画像が最終的に読み込まれる前にイベントが登録されるため、コンソールにはimage loaded
メッセージが表示されます。
image.jpg
がscript.js
より小さいこのシナリオでは、投稿の冒頭で説明されている問題を確認できます。 onLoad
イベントはトリガーされません。
シナリオ2でonLoad
イベントをトリガーするために何ができますか?
レンダリング時に画像の準備ができているかどうかを検出するには、純粋なjavascript complete
オブジェクトのimg
プロパティを確認する必要があります。
constructor(props) {
super(props);
this.state = { loaded: false };
this.handleImageLoaded = this.handleImageLoaded.bind(this);
this.image = React.createRef();
}
componentDidMount() {
const img = this.image.current;
if (img && img.complete) {
this.handleImageLoaded();
}
}
handleImageLoaded() {
if (!this.state.loaded) {
console.log('image loaded');
this.setState({ loaded: true });
}
}
render() {
return (
<img src='image.jpg' ref={this.image} onLoad={this.handleImageLoaded} />
);
}
complete
イベントを適用する前に、イメージのonload
プロパティを確認できます。
if (!img.complete) {
// add onload listener here
}
もう1つの方法は、refを使用して両方のシナリオをカバーすることです。
<img
ref={(input) => {
// onLoad replacement for SSR
if (!input) { return; }
const img = input;
const updateFunc = () => {
this.setState({ loaded: true });
};
img.onload = updateFunc;
if (img.complete) {
updateFunc();
}
}}
src={imgSrc}
alt={imgAlt}
/>
img.completeは、srcのロードが失敗した場合でもtrueです。
complete-ブラウザが画像のフェッチを終了した場合にtrueとなるブール値成功したかどうかにかかわらずを返します。画像にsrc値がない場合もtrueを示します。
state = {
isLoading: true,
hasError: false,
}
myRef = React.createRef();
componentDidMount() {
const img = this.myRef.current;
if (img && img.complete) {
if (img.naturalWidth === 0) {
this.handleOnError();
} else {
this.handleImageLoaded();
}
}
}
handleImageLoaded = () => {
if (this.state.isLoading) {
this.setState({ isLoading: false });
}
}
handleOnError = () => {
this.setState({ hasError: true });
}
render() {
return (
<img
src={src}
alt={alt}
ref={this.myRef}
onError={this.handleOnError}
onLoad={this.handleOnLoad}
/>
);
}
componentDidMount() {
const testImg = new Image();
testImg.onerror = this.handleOnError;
testImg.onload = this.handleImageLoaded;
testImg.src = this.props.src; // important to set eventlisteners before src
}