Image onLoad event in isomorphic/universal react - register event after image is loaded

老子叫甜甜 提交于 2019-12-03 05:01:34

问题


In isomorphic rendered page image can be downloaded before main script.js file. So image can be already loaded before react register onLoad event - never trigger this event.

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

Scenario 1 - image.jpg is bigger than script.js

In this scenario everything is working fine. Event is registered before image is finally loaded so in console is image loaded message.


Scenario 2 - image.jpg is smaller than script.js

This scenario you can see problem described at the beginning of post. onLoad event is not triggered.


Question

What can I do in order to trigger onLoad event in scenario 2?


EDIT: Soviut answer implementation

To detect if image is ready on render you should check complete property on pure javascript img object:

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

回答1:


You could check the complete property on the image before applying the onload event.

if (!img.complete) {
    // add onload listener here
}



回答2:


Another way is to use ref and cover those both scenarios:

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



回答3:


img.complete is true even when the src load fails.

complete - Returns a Boolean that is true if the browser has finished fetching the image, whether successful or not. It also shows true, if the image has no src value.

  1. Use naturalWidth as determinant whether the img load was successfull or not
    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}
            />
        );
    }
  1. Another way is to add "check" image in componentDidMount a set eventHandler to it and let the check image be the one to handle 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
}




回答4:


<img
    src={this.props.imageUrl}
    onLoad={this.handleImageLoaded.bind(this)}
    onError={this.handleImageErrored.bind(this)}
/>


来源:https://stackoverflow.com/questions/39777833/image-onload-event-in-isomorphic-universal-react-register-event-after-image-is

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!