web-dev-qa-db-fra.com

Evénement image onLoad dans isomorphic/universal react - enregistre l'événement après le chargement de l'image

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} />
    );
}

Scénario 1 - image.jpg est plus grand que script.js

 image.jpg is bigger than 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.


Scénario 2 - image.jpg est inférieur à script.js

 image.jpg is smaller than 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é. 


Question

Que puis-je faire pour déclencher un événement onLoad dans scenario 2


EDIT: Implémentation Soviut de réponse

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} />
    );
}
12
Everettss

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
}
13
Soviut

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}
/>
2
Idan Gozlan

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.

  1. 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 ( );}

  2. 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
}
1
michalhonc