diff --git a/packages/gatsby-image/README.md b/packages/gatsby-image/README.md
index 9ca5a9818fc92..c8b9448ad0bcc 100644
--- a/packages/gatsby-image/README.md
+++ b/packages/gatsby-image/README.md
@@ -276,6 +276,7 @@ prop. e.g. ``
| `placeholderClassName` | `string` | A class that is passed to the placeholder `img` element |
| `backgroundColor` | `string` / `bool` | Set a colored background placeholder. If true, uses "lightgray" for the color. You can also pass in any valid color string. |
| `onLoad` | `func` | A callback that is called when the full-size image has loaded. |
+| `onStartLoad` | `func` | A callback that is called when the full-size image starts loading, it gets the parameter { wasCached: boolean } provided. |
| `onError` | `func` | A callback that is called when the image fails to load. |
| `Tag` | `string` | Which HTML tag to use for wrapping elements. Defaults to `div`. |
| `critical` | `bool` | Opt-out of lazy-loading behavior. Defaults to `false`. |
diff --git a/packages/gatsby-image/index.d.ts b/packages/gatsby-image/index.d.ts
index 7309346218bfe..c2252b03c162b 100644
--- a/packages/gatsby-image/index.d.ts
+++ b/packages/gatsby-image/index.d.ts
@@ -1,22 +1,48 @@
-import * as React from "react";
+import * as React from "react"
+
+interface FixedObject {
+ width: number
+ height: number
+ src: string
+ srcSet: string
+ base64?: string
+ tracedSVG?: string
+ srcWebp?: string
+ srcSetWebp?: string
+}
+
+interface FluidObject {
+ aspectRatio: number
+ src: string
+ srcSet: string
+ sizes: string
+ base64: string
+ tracedSVG: string
+ srcWebp: string
+ srcSetWebp: string
+}
interface GatsbyImageProps {
- resolutions?: object;
- sizes?: object;
- fixed?: object;
- fluid?: object;
- fadeIn?: boolean;
- title?: string;
- alt?: string;
- className?: string | object;
- critical?: boolean;
- style?: object;
- imgStyle?: object;
- placeholderStyle?: object;
- backgroundColor?: string | boolean;
- onLoad?: (event: any) => void;
- onError?: (event: any) => void;
- Tag?: string;
+ resolutions?: FixedObject
+ sizes?: FluidObject
+ fixed?: FixedObject
+ fluid?: FluidObject
+ fadeIn?: boolean
+ title?: string
+ alt?: string
+ className?: string | object
+ critical?: boolean
+ style?: object
+ imgStyle?: object
+ placeholderStyle: object
+ backgroundColor?: string | boolean
+ onLoad?: () => void
+ onStartLoad?: (param: { wasCached: boolean }) => void
+ onError?: (event: any) => void
+ Tag?: string
}
-export default class GatsbyImage extends React.Component {}
+export default class GatsbyImage extends React.Component<
+ GatsbyImageProps,
+ any
+> {}
diff --git a/packages/gatsby-image/src/index.js b/packages/gatsby-image/src/index.js
index accd045662076..4686182ca244e 100644
--- a/packages/gatsby-image/src/index.js
+++ b/packages/gatsby-image/src/index.js
@@ -26,12 +26,17 @@ const inImageCache = props => {
? convertedProps.fluid.src
: convertedProps.fixed.src
- if (imageCache[src]) {
- return true
- } else {
- imageCache[src] = true
- return false
- }
+ return imageCache[src] || false
+}
+
+const activateCacheForImage = props => {
+ const convertedProps = convertProps(props)
+ // Find src
+ const src = convertedProps.fluid
+ ? convertedProps.fluid.src
+ : convertedProps.fixed.src
+
+ imageCache[src] = true
}
let io
@@ -172,6 +177,9 @@ class Image extends React.Component {
}
componentDidMount() {
+ if (this.state.isVisible && typeof this.props.onStartLoad === `function`) {
+ this.props.onStartLoad({ wasCached: inImageCache(this.props) })
+ }
if (this.props.critical) {
const img = this.imageRef.current
if (img && img.complete) {
@@ -183,12 +191,21 @@ class Image extends React.Component {
handleRef(ref) {
if (this.state.IOSupported && ref) {
listenToIntersections(ref, () => {
- this.setState({ isVisible: true })
+ if (
+ !this.state.isVisible &&
+ typeof this.props.onStartLoad === `function`
+ ) {
+ this.props.onStartLoad({ wasCached: inImageCache(this.props) })
+ }
+
+ this.setState({ isVisible: true, imgLoaded: false })
})
}
}
handleImageLoaded() {
+ activateCacheForImage(this.props)
+
this.setState({ imgLoaded: true })
if (this.state.seenBefore) {
this.setState({ fadeIn: false })
@@ -462,6 +479,7 @@ Image.propTypes = {
backgroundColor: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
onLoad: PropTypes.func,
onError: PropTypes.func,
+ onStartLoad: PropTypes.func,
Tag: PropTypes.string,
}