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} />
);
}
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.
image.jpg is smaller than script.js

This scenario you can see problem described at the beginning of post. onLoad event is not triggered.
What can I do in order to trigger onLoad event in scenario 2?
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} />
);
}
You could check the complete property on the image before applying the onload event.
if (!img.complete) {
// add onload listener here
}
This is all a bit tidier with Hooks:
const useImageLoaded = () => {
const [loaded, setLoaded] = useState(false)
const ref = useRef()
const onLoad = () => {
setLoaded(true)
}
useEffect(() => {
if (ref.current && ref.current.complete) {
onLoad()
}
})
return [ref, loaded, onLoad]
}
const SomeComponent = ({ src }) => {
const [ref, loaded, onLoad] = useImageLoaded()
return (
<div>
<img ref={ref} onLoad={onLoad} src={src} alt="" />
{loaded && <h1>Loaded!</h1>}
</div>
)
}
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}
/>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With