Skip to content

Commit 1d25a95

Browse files
Kalle Ottpieh
authored andcommitted
feat(gatsby-image): add onStartLoad prop (#6702)
* implementation of the onStartLoad handler for gatsby-image * update to typescript declarations of gatsby-image * changed double quotes to backticks * updated declaration file to better represent current state of gatsby-image * make sure onStartLoad is only fired once * fixed image cache information store provide cache information in the onStartLoad handler * updatede readme * better name for cache setter * lint fix
1 parent 9dfd95a commit 1d25a95

File tree

3 files changed

+70
-25
lines changed

3 files changed

+70
-25
lines changed

packages/gatsby-image/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,7 @@ prop. e.g. `<Img fluid={fluid} />`
276276
| `placeholderClassName` | `string` | A class that is passed to the placeholder `img` element |
277277
| `backgroundColor` | `string` / `bool` | Set a colored background placeholder. If true, uses "lightgray" for the color. You can also pass in any valid color string. |
278278
| `onLoad` | `func` | A callback that is called when the full-size image has loaded. |
279+
| `onStartLoad` | `func` | A callback that is called when the full-size image starts loading, it gets the parameter { wasCached: boolean } provided. |
279280
| `onError` | `func` | A callback that is called when the image fails to load. |
280281
| `Tag` | `string` | Which HTML tag to use for wrapping elements. Defaults to `div`. |
281282
| `critical` | `bool` | Opt-out of lazy-loading behavior. Defaults to `false`. |

packages/gatsby-image/index.d.ts

Lines changed: 44 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,48 @@
1-
import * as React from "react";
1+
import * as React from "react"
2+
3+
interface FixedObject {
4+
width: number
5+
height: number
6+
src: string
7+
srcSet: string
8+
base64?: string
9+
tracedSVG?: string
10+
srcWebp?: string
11+
srcSetWebp?: string
12+
}
13+
14+
interface FluidObject {
15+
aspectRatio: number
16+
src: string
17+
srcSet: string
18+
sizes: string
19+
base64: string
20+
tracedSVG: string
21+
srcWebp: string
22+
srcSetWebp: string
23+
}
224

325
interface GatsbyImageProps {
4-
resolutions?: object;
5-
sizes?: object;
6-
fixed?: object;
7-
fluid?: object;
8-
fadeIn?: boolean;
9-
title?: string;
10-
alt?: string;
11-
className?: string | object;
12-
critical?: boolean;
13-
style?: object;
14-
imgStyle?: object;
15-
placeholderStyle?: object;
16-
backgroundColor?: string | boolean;
17-
onLoad?: (event: any) => void;
18-
onError?: (event: any) => void;
19-
Tag?: string;
26+
resolutions?: FixedObject
27+
sizes?: FluidObject
28+
fixed?: FixedObject
29+
fluid?: FluidObject
30+
fadeIn?: boolean
31+
title?: string
32+
alt?: string
33+
className?: string | object
34+
critical?: boolean
35+
style?: object
36+
imgStyle?: object
37+
placeholderStyle: object
38+
backgroundColor?: string | boolean
39+
onLoad?: () => void
40+
onStartLoad?: (param: { wasCached: boolean }) => void
41+
onError?: (event: any) => void
42+
Tag?: string
2043
}
2144

22-
export default class GatsbyImage extends React.Component<GatsbyImageProps, any> {}
45+
export default class GatsbyImage extends React.Component<
46+
GatsbyImageProps,
47+
any
48+
> {}

packages/gatsby-image/src/index.js

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,17 @@ const inImageCache = props => {
2626
? convertedProps.fluid.src
2727
: convertedProps.fixed.src
2828

29-
if (imageCache[src]) {
30-
return true
31-
} else {
32-
imageCache[src] = true
33-
return false
34-
}
29+
return imageCache[src] || false
30+
}
31+
32+
const activateCacheForImage = props => {
33+
const convertedProps = convertProps(props)
34+
// Find src
35+
const src = convertedProps.fluid
36+
? convertedProps.fluid.src
37+
: convertedProps.fixed.src
38+
39+
imageCache[src] = true
3540
}
3641

3742
let io
@@ -172,6 +177,9 @@ class Image extends React.Component {
172177
}
173178

174179
componentDidMount() {
180+
if (this.state.isVisible && typeof this.props.onStartLoad === `function`) {
181+
this.props.onStartLoad({ wasCached: inImageCache(this.props) })
182+
}
175183
if (this.props.critical) {
176184
const img = this.imageRef.current
177185
if (img && img.complete) {
@@ -183,12 +191,21 @@ class Image extends React.Component {
183191
handleRef(ref) {
184192
if (this.state.IOSupported && ref) {
185193
listenToIntersections(ref, () => {
186-
this.setState({ isVisible: true })
194+
if (
195+
!this.state.isVisible &&
196+
typeof this.props.onStartLoad === `function`
197+
) {
198+
this.props.onStartLoad({ wasCached: inImageCache(this.props) })
199+
}
200+
201+
this.setState({ isVisible: true, imgLoaded: false })
187202
})
188203
}
189204
}
190205

191206
handleImageLoaded() {
207+
activateCacheForImage(this.props)
208+
192209
this.setState({ imgLoaded: true })
193210
if (this.state.seenBefore) {
194211
this.setState({ fadeIn: false })
@@ -462,6 +479,7 @@ Image.propTypes = {
462479
backgroundColor: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
463480
onLoad: PropTypes.func,
464481
onError: PropTypes.func,
482+
onStartLoad: PropTypes.func,
465483
Tag: PropTypes.string,
466484
}
467485

0 commit comments

Comments
 (0)