- If you are doing SSR, don't forget to check if an image is loaded before mount.
img.onload
is not captured when the image is loaded before JavaScript is executed. - To tweak
ref
beforecomponentDidMount
is executed, extend the class and override the method to set theref
. It's much cleaner than stubbing the method. - To call its super method of a bound method with Babel, save the super method as another class property. Class properties are directly set on an instance instead of constructor's prototype.
Last active
January 16, 2024 14:13
-
-
Save shuhei/87178387e49948bfa776ca61b69d9e61 to your computer and use it in GitHub Desktop.
img.onload and unit test in React
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import * as React from 'react'; | |
import { mount } from 'enzyme'; | |
import sinon from 'sinon'; | |
function isImageLoaded(img: HTMLImageElement) { | |
return img.complete && img.naturalHeight > 0; | |
} | |
type Props = { | |
src: string, | |
onLoad: () => void, | |
}; | |
class Image extends React.Component<Props> { | |
imageElement: ?HTMLImageElement; | |
componentDidMount() { | |
if (this.imageElement && isImageLoaded(this.imageElement)) { | |
this.props.onLoad(); | |
} | |
} | |
setImageElement = (img: ?HTMLImageElement) => { | |
this.imageElement = img; | |
}; | |
render() { | |
const { src, onLoad } = this.props; | |
return ( | |
<img src={src} ref={this.setImageElement} onLoad={onLoad} /> | |
); | |
} | |
} | |
it('calls onLoad callback on load', () => { | |
const onLoad = sinon.spy(); | |
const wrapper = mount(<Image src=“foo” onLoad={onLoad} />); | |
wrapper.find('img').simulate('load'); | |
assert(onLoad.calledOnce); | |
}); | |
it('calls onLoad callback if image is loaded on mount', () => { | |
class LoadedImage extends Image { | |
originalSetImageElement = this.setImageElement; | |
setImageElement = (img) => { | |
if (img) { | |
Object.defineProperty(img, 'complete', { value: true }); | |
Object.defineProperty(img, 'naturalHeight', { value: 100 }); | |
} | |
this.originalSetImageElement(img); | |
}; | |
} | |
const onLoad = sinon.spy(); | |
const wrapper = mount(<LoadedImage src=“foo” onLoad={onLoad} />); | |
assert(onLoad.calledOnce); | |
}); | |
class LoadedImage extends Image { | |
setImageElement = (img) => { | |
if (img) { | |
Object.defineProperty(img, 'complete', { value: true }); | |
Object.defineProperty(img, 'naturalHeight', { value: 100 }); | |
} | |
// Doesn't work... | |
super.setImageElement(img); | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment