-
Notifications
You must be signed in to change notification settings - Fork 26
/
LazyImage.tsx
80 lines (69 loc) · 2.22 KB
/
LazyImage.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
import React from "react";
import {
LazyImageFull,
CommonLazyImageProps,
ImageState,
ImageProps
} from "./LazyImageFull";
/**
* Valid props for LazyImage
*/
export interface LazyImageRenderPropArgs {
imageProps: ImageProps;
}
export interface RefArg {
/** When not loading eagerly, a ref to bind to the DOM element. This is needed for the intersection calculation to work. */
ref?: React.RefObject<any> | ((node?: Element | null) => void);
}
export interface LazyImageProps extends CommonLazyImageProps {
/** Component to display once image has loaded */
actual: (args: LazyImageRenderPropArgs) => React.ReactElement<{}>;
/** Component to display while image has not been requested
* @default: undefined
*/
placeholder: (
args: LazyImageRenderPropArgs & RefArg
) => React.ReactElement<{}>;
/** Component to display while the image is loading
* @default placeholder, if defined
*/
loading?: () => React.ReactElement<{}>;
/** Component to display if the image fails to load
* @default actual (broken image)
*/
error?: () => React.ReactElement<{}>;
}
/**
* Component that preloads the image once it is in the viewport,
* and then swaps it in. Has predefined rendering logic, but the
* specifics are up to the caller.
*/
export const LazyImage: React.FC<LazyImageProps> = ({
actual,
placeholder,
loading,
error,
...rest
}) => (
<LazyImageFull {...rest}>
{({ imageState, imageProps, ref }) => {
// Call the appropriate render callback based on the state
// and the props specified, passing on relevant props.
switch (imageState) {
case ImageState.NotAsked:
return !!placeholder && placeholder({ imageProps, ref });
case ImageState.Loading:
// Only render loading if specified, otherwise placeholder
return !!loading
? loading()
: !!placeholder && placeholder({ imageProps, ref });
case ImageState.LoadSuccess:
return actual({ imageProps });
case ImageState.LoadError:
// Only render error if specified, otherwise actual (broken image)
return !!error ? error() : actual({ imageProps });
}
}}
</LazyImageFull>
);
LazyImage.displayName = "LazyImage";