Skip to content

Instantly share code, notes, and snippets.

@shuhei
Last active January 16, 2024 14:13
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save shuhei/87178387e49948bfa776ca61b69d9e61 to your computer and use it in GitHub Desktop.
Save shuhei/87178387e49948bfa776ca61b69d9e61 to your computer and use it in GitHub Desktop.
img.onload and unit test in React
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);
};
}

TIL about React, Enzyme and Babel on 19.04.2018

  1. 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.
  2. To tweak ref before componentDidMount is executed, extend the class and override the method to set the ref. It's much cleaner than stubbing the method.
  3. 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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment