forked from vivaxy/react-native-auto-height-image
-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathfastAutoHeightImage.js
93 lines (81 loc) · 2.36 KB
/
fastAutoHeightImage.js
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
81
82
83
84
85
86
87
88
89
90
91
92
93
/**
* @since 2017-04-11 19:10:08
* @author vivaxy
*/
import React, { PureComponent } from 'react';
import Image from 'react-native-android-image-polyfill';
import FastImage from 'react-native-fast-image'
import { StyleSheet } from 'react-native';
import PropTypes from 'prop-types';
import { getImageSizeFitWidth, getImageSizeFitWidthFromCache } from './cache';
import { NOOP, DEFAULT_HEIGHT } from './helpers';
// remove `resizeMode` props from `Image.propTypes`
const { resizeMode, ...ImagePropTypes } = Image.propTypes;
export default class FastAutoHeightImage extends PureComponent {
static propTypes = {
...ImagePropTypes,
width: PropTypes.number.isRequired,
onHeightChange: PropTypes.func
};
static defaultProps = {
onHeightChange: NOOP
};
constructor(props) {
super(props);
this.setInitialImageHeight();
}
async componentDidMount() {
this.hasMounted = true;
await this.updateImageHeight(this.props);
}
async componentWillReceiveProps(nextProps) {
await this.updateImageHeight(nextProps);
}
componentWillUnmount() {
this.hasMounted = false;
}
setInitialImageHeight() {
const { source, width, onHeightChange } = this.props;
const { height = DEFAULT_HEIGHT } = getImageSizeFitWidthFromCache(
source,
width
);
this.state = { height };
this.styles = StyleSheet.create({ image: { width, height } });
onHeightChange(height);
}
async updateImageHeight(props) {
if (
this.state.height === DEFAULT_HEIGHT ||
this.props.width !== props.width ||
this.props.source !== props.source
) {
// image height could not be `0`
const { source, width, onHeightChange } = props;
try {
const { height } = await getImageSizeFitWidth(source, width);
this.styles = StyleSheet.create({ image: { width, height } });
if (this.hasMounted) {
// guard `this.setState` to be valid
this.setState({ height });
onHeightChange(height);
}
} catch (ex) {
if (this.props.onError) {
this.props.onError(ex);
}
}
}
}
render() {
// remove `width` prop from `restProps`
const { source, style, width, ...restProps } = this.props;
return (
<FastImage
source={source}
style={[this.styles.image, style]}
{...restProps}
/>
);
}
}