Dans les images rendues isomorphes peuvent être téléchargées avant le fichier script.js
principal. Ainsi, l'image peut être déjà chargée avant l'événement react
register onLoad
- ne déclenchez jamais cet événement.
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
est plus grand que script.js
Dans ce scénario, tout fonctionne bien. L'événement est enregistré avant le chargement définitif de l'image. Dans la console, le message image loaded
s'affiche.
image.jpg
est inférieur à script.js
Ce scénario, vous pouvez voir le problème décrit au début du post. onLoad
L'événement n'est pas déclenché.
Que puis-je faire pour déclencher un événement onLoad
dans scenario 2?
Pour détecter si l'image est prête au rendu, vous devez vérifier la propriété complete
sur un objet javascript pur 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} />
);
}
Vous pouvez vérifier la propriété complete
sur l'image avant d'appliquer l'événement onload
.
if (!img.complete) {
// add onload listener here
}
Une autre façon consiste à utiliser ref et à couvrir ces deux scénarios:
<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 est vrai même lorsque le chargement de src échoue.
complete - Retourne un booléen vrai si le navigateur a fini de récupérer l'image, que ce soit avec succès ou non . Il indique également true si l'image n'a pas de valeur src.
Utilisez naturalWidth comme déterminant de la réussite ou non de la charge d'img
state = { isLoading: true, hasError: false, }
myRef = React.createRef ();
composantDidMount () { 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 () { revenir ( );}
Une autre méthode consiste à ajouter une image "check" dans composantDidMount à un eventHandler défini et à laisser l’image de contrôle être celle qui gérera eventListeners
componentDidMount() {
const testImg = new Image();
testImg.onerror = this.handleOnError;
testImg.onload = this.handleImageLoaded;
testImg.src = this.props.src; // important to set eventlisteners before src
}