import React from 'react';
import {
View, Dimensions, ViewPropTypes, FlatList,
} from 'react-native';
import PropTypes from 'prop-types';
import { chunkArray, calculateDimensions, generateStyles } from './utils';
class FlatGrid extends React.Component {
constructor(props) {
super(props);
this.renderRow = this.renderRow.bind(this);
this.onLayout = this.onLayout.bind(this);
const { staticDimension, horizontal } = props;
// Calculate total dimensions and set to state
let totalDimension = staticDimension;
if (!staticDimension) {
const dimension = horizontal ? 'height' : 'width';
totalDimension = Dimensions.get('window')[dimension];
}
this.state = {
totalDimension,
};
}
onLayout(e) {
const { staticDimension, horizontal, onLayout } = this.props;
const { totalDimension } = this.state;
if (!staticDimension) {
const { width, height } = e.nativeEvent.layout || {};
const newTotalDimension = horizontal ? height : width;
if (totalDimension !== newTotalDimension) {
this.setState({
totalDimension: newTotalDimension,
});
}
}
// call onLayout prop if passed
if (onLayout) {
onLayout(e);
}
}
renderRow({
rowItems,
rowIndex,
separators,
isLastRow,
itemsPerRow,
rowStyle,
containerStyle,
}) {
const {
spacing, horizontal, itemContainerStyle, renderItem,
} = this.props;
// To make up for the top padding
let additionalRowStyle = {};
if (isLastRow) {
additionalRowStyle = {
...(!horizontal ? { marginBottom: spacing } : {}),
...(horizontal ? { marginRight: spacing } : {}),
};
}
return (
{rowItems.map((item, i) => (
{renderItem({
item,
index: (rowIndex * itemsPerRow) + i,
separators,
rowIndex,
})}
))}
);
}
render() {
const {
items,
style,
spacing,
fixed,
itemDimension,
renderItem,
horizontal,
onLayout,
staticDimension,
itemContainerStyle,
...restProps
} = this.props;
const { totalDimension } = this.state;
const { containerDimension, itemsPerRow, fixedSpacing } = calculateDimensions({
itemDimension,
staticDimension,
totalDimension,
spacing,
fixed,
});
const { containerStyle, rowStyle } = generateStyles({
horizontal,
itemDimension,
containerDimension,
spacing,
fixedSpacing,
fixed,
});
const rows = chunkArray(items, itemsPerRow); // Splitting the data into rows
return (
this.renderRow({
rowItems: item,
rowIndex: index,
isLastRow: index === rows.length - 1,
itemsPerRow,
rowStyle,
containerStyle,
})
}
style={[
{
...(horizontal ? { paddingLeft: spacing } : { paddingTop: spacing }),
},
style,
]}
onLayout={this.onLayout}
keyExtractor={(_, index) => `row_${index}`}
{...restProps}
horizontal={horizontal}
ref={(flatList) => { this.flatList = flatList; }}
/>
);
}
}
FlatGrid.propTypes = {
renderItem: PropTypes.func.isRequired,
items: PropTypes.arrayOf(PropTypes.any).isRequired,
itemDimension: PropTypes.number,
fixed: PropTypes.bool,
spacing: PropTypes.number,
style: ViewPropTypes.style,
itemContainerStyle: ViewPropTypes.style,
staticDimension: PropTypes.number,
horizontal: PropTypes.bool,
onLayout: PropTypes.func,
};
FlatGrid.defaultProps = {
fixed: false,
itemDimension: 120,
spacing: 10,
style: {},
itemContainerStyle: undefined,
staticDimension: undefined,
horizontal: false,
onLayout: null,
};
export default FlatGrid;