Skip to content

Commit c5b4bbd

Browse files
author
Nir Maoz
authored
Fix lazy loading of responsive images (#182)
1 parent d4b83c4 commit c5b4bbd

File tree

3 files changed

+46
-13
lines changed

3 files changed

+46
-13
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
describe('Lazy Responsive Image', () => {
2+
beforeEach(() => {
3+
// runs before each test in the block
4+
cy.visit('/');
5+
cy.get('#lazyResponsiveBtn').click(); // Click on button
6+
});
7+
it('Should not have src attribute when not in view', () => {
8+
cy.get('#lazyResponsive')
9+
.should('not.be.visible')
10+
.should('not.have.attr', 'src');
11+
});
12+
it('Should have src attribute when view', () => {
13+
cy.scrollTo(0, 3000);
14+
cy.get('#lazyResponsive')
15+
.should('be.visible')
16+
.should('have.attr', 'src').should('equal', 'http://res.cloudinary.com/demo/image/upload/c_scale,w_400/sample');
17+
});
18+
});

e2e-test/src/App.js

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ const tests = [
66
'responsive',
77
'placeholder',
88
'lazy',
9-
'lazyPlaceholder'
9+
'lazyPlaceholder',
10+
'lazyResponsive'
1011
];
1112

1213
function App() {
@@ -70,6 +71,18 @@ function App() {
7071
</div>
7172
</div>
7273
}
74+
{test === 'lazyResponsive' &&
75+
<div>
76+
<h1>Lazy Responsive</h1>
77+
<div style={{marginTop: '3000px'}}>
78+
<div style={{width: "330px"}}>
79+
<Image id="lazyResponsive" publicId="sample" cloudName="demo" width="auto" crop="scale" loading="lazy"
80+
responsive>
81+
</Image>
82+
</div>
83+
</div>
84+
</div>
85+
}
7386
</Fragment>
7487
);
7588
}

src/components/Image/Image.js

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@ class Image extends CloudinaryComponent {
5050
* @return attributes for the underlying <img> element.
5151
*/
5252
getAttributes = (additionalOptions = {}) => {
53-
const {isInView} = this.state;
5453
const {placeholder} = additionalOptions;
5554
const options = {...this.getOptions(), ...additionalOptions};
5655
const {nonCloudinaryProps} = extractCloudinaryProps(options);
@@ -69,7 +68,7 @@ class Image extends CloudinaryComponent {
6968
}
7069

7170
// Set data-src if lazy loading and not in view
72-
if (!isInView && this.shouldLazyLoad(options)) {
71+
if (this.shouldLazyLoad()) {
7372
attributes['data-src'] = attributes.dataSrc || attributes.src;
7473
delete attributes.src;
7574
}
@@ -86,15 +85,16 @@ class Image extends CloudinaryComponent {
8685
* Update this image using cloudinary-core
8786
*/
8887
update = () => {
89-
const {isInView} = this.state;
90-
91-
if (this.isResponsive()) {
92-
const removeListener = makeElementResponsive(this.imgElement.current, this.getOptions());
93-
this.listenerRemovers.push(removeListener);
94-
}
95-
96-
if (!isInView && this.shouldLazyLoad(this.getExtendedProps())) {
88+
// Handle lazy loading
89+
if (this.shouldLazyLoad()) {
90+
// Will set this.state.isInView = true when in view
9791
Util.detectIntersection(this.imgElement.current, this.onIntersect);
92+
} else {
93+
// Handle responsive only if lazy loading wasn't requested or already handled
94+
if (this.isResponsive()) {
95+
const removeListener = makeElementResponsive(this.imgElement.current, this.getOptions());
96+
this.listenerRemovers.push(removeListener);
97+
}
9898
}
9999
}
100100

@@ -115,8 +115,10 @@ class Image extends CloudinaryComponent {
115115
}
116116
};
117117

118-
shouldLazyLoad = ({loading}) => {
119-
return loading === "lazy" || loading === "auto";
118+
shouldLazyLoad = () => {
119+
const {loading} = this.getExtendedProps();
120+
const {isInView} = this.state;
121+
return !isInView && (loading === "lazy" || loading === "auto");
120122
}
121123

122124
/**

0 commit comments

Comments
 (0)