Skip to content

Commit c64988e

Browse files
committed
fixed ListFooter and OnEndReached
- List Footer is not duplicated for each column (only one list footer is now present) - OnEndReached now is properly called for the whole component instead of for each column
1 parent f096252 commit c64988e

File tree

1 file changed

+49
-51
lines changed

1 file changed

+49
-51
lines changed

src/MasonryList.js

Lines changed: 49 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,11 @@ const _stateFromProps = ({ numColumns, data, getHeightForItem }) => {
4444
export type Props = {
4545
data: Array<any>,
4646
numColumns: number,
47-
renderItem: ({ item: any, index: number, column: number }) => ?React.Element<
48-
any,
49-
>,
47+
renderItem: ({ item: any, index: number, column: number }) => ?React.Element<any>,
5048
getHeightForItem: ({ item: any, index: number }) => number,
5149
ListHeaderComponent?: ?React.ComponentType<any>,
5250
ListEmptyComponent?: ?React.ComponentType<any>,
51+
ListFooterComponent?: ?React.ComponentType<any>,
5352
/**
5453
* Used to extract a unique key for a given item at the specified index. Key is used for caching
5554
* and as the react key to track item re-ordering. The default extractor checks `item.key`, then
@@ -86,11 +85,7 @@ type State = {
8685
// onLayout since it exists on both).
8786
class FakeScrollView extends React.Component<{ style?: any, children?: any }> {
8887
render() {
89-
return (
90-
<View style={this.props.style}>
91-
{this.props.children}
92-
</View>
93-
);
88+
return <View style={this.props.style}>{this.props.children}</View>;
9489
}
9590
}
9691

@@ -104,10 +99,7 @@ export default class MasonryList extends React.Component<Props, State> {
10499
<ScrollView
105100
{...props}
106101
refreshControl={
107-
<RefreshControl
108-
refreshing={props.refreshing}
109-
onRefresh={props.onRefresh}
110-
/>
102+
<RefreshControl refreshing={props.refreshing} onRefresh={props.onRefresh} />
111103
}
112104
/>
113105
);
@@ -119,9 +111,10 @@ export default class MasonryList extends React.Component<Props, State> {
119111
state = _stateFromProps(this.props);
120112
_listRefs: Array<?VirtualizedList> = [];
121113
_scrollRef: ?ScrollView;
122-
_endsReached = 0;
114+
_endReached = false;
123115

124-
componentWillReceiveProps(newProps: Props) {
116+
//TODO: UPDATE to REACT 16.3 req
117+
UNSAFE_componentWillReceiveProps(newProps: Props) {
125118
this.setState(_stateFromProps(newProps));
126119
}
127120

@@ -145,59 +138,61 @@ export default class MasonryList extends React.Component<Props, State> {
145138
}
146139
}
147140

148-
_onLayout = event => {
149-
this._listRefs.forEach(
150-
list => list && list._onLayout && list._onLayout(event),
151-
);
141+
_onLayout = (event: Object) => {
142+
this._listRefs.forEach(list => list && list._onLayout && list._onLayout(event));
152143
};
153144

154-
_onContentSizeChange = (width, height) => {
145+
_onContentSizeChange = (width: number, height: number) => {
155146
this._listRefs.forEach(
156-
list =>
157-
list &&
158-
list._onContentSizeChange &&
159-
list._onContentSizeChange(width, height),
147+
list => list && list._onContentSizeChange && list._onContentSizeChange(width, height)
160148
);
161149
};
162150

163-
_onScroll = event => {
151+
_onScroll = (event: Object) => {
164152
if (this.props.onScroll) {
165153
this.props.onScroll(event);
166154
}
167-
this._listRefs.forEach(
168-
list => list && list._onScroll && list._onScroll(event),
169-
);
155+
this._listRefs.forEach(list => list && list._onScroll && list._onScroll(event));
170156
};
171157

172-
_onScrollBeginDrag = event => {
158+
_onScrollBeginDrag = (event: Object) => {
173159
if (this.props.onScrollBeginDrag) {
174160
this.props.onScrollBeginDrag(event);
175161
}
176162
this._listRefs.forEach(
177-
list => list && list._onScrollBeginDrag && list._onScrollBeginDrag(event),
163+
list => list && list._onScrollBeginDrag && list._onScrollBeginDrag(event)
178164
);
179165
};
180166

181-
_onScrollEndDrag = event => {
167+
_onScrollEndDrag = (event: Object) => {
182168
if (this.props.onScrollEndDrag) {
183169
this.props.onScrollEndDrag(event);
184170
}
185-
this._listRefs.forEach(
186-
list => list && list._onScrollEndDrag && list._onScrollEndDrag(event),
187-
);
171+
this._listRefs.forEach(list => list && list._onScrollEndDrag && list._onScrollEndDrag(event));
188172
};
189173

190-
_onMomentumScrollEnd = event => {
174+
_onMomentumScrollEnd = (event: Object) => {
191175
if (this.props.onMomentumScrollEnd) {
192176
this.props.onMomentumScrollEnd(event);
193177
}
194178
this._listRefs.forEach(
195-
list =>
196-
list && list._onMomentumScrollEnd && list._onMomentumScrollEnd(event),
179+
list => list && list._onMomentumScrollEnd && list._onMomentumScrollEnd(event)
197180
);
198181
};
199182

200-
_getItemLayout = (columnIndex, rowIndex) => {
183+
_onEndReached = (info: { distanceFromEnd: number }) => {
184+
if (this._endReached) {
185+
return;
186+
}
187+
this._endReached = true;
188+
if (this.props.onEndReached) {
189+
Promise.resolve(this.props.onEndReached(info)).then(() => {
190+
this._endReached = false;
191+
});
192+
}
193+
};
194+
195+
_getItemLayout = (columnIndex: number, rowIndex: number) => {
201196
const column = this.state.columns[columnIndex];
202197
let offset = 0;
203198
for (let ii = 0; ii < rowIndex; ii += 1) {
@@ -208,19 +203,20 @@ export default class MasonryList extends React.Component<Props, State> {
208203

209204
_renderScrollComponent = () => <FakeScrollView style={styles.column} />;
210205

211-
_getItemCount = data => data.length;
206+
_getItemCount = (data: any[]) => data.length;
212207

213-
_getItem = (data, index) => data[index];
208+
_getItem = (data: any[], index: number) => data[index];
214209

210+
//$FlowFixMe
215211
_captureScrollRef = ref => (this._scrollRef = ref);
216212

217213
render() {
218214
const {
219215
renderItem,
220216
ListHeaderComponent,
221217
ListEmptyComponent,
218+
ListFooterComponent,
222219
keyExtractor,
223-
onEndReached,
224220
...props
225221
} = this.props;
226222
let headerElement;
@@ -231,29 +227,30 @@ export default class MasonryList extends React.Component<Props, State> {
231227
if (ListEmptyComponent) {
232228
emptyElement = <ListEmptyComponent />;
233229
}
234-
230+
let footerElement;
231+
if (ListFooterComponent) {
232+
footerElement = <ListFooterComponent />;
233+
}
235234
const content = (
236235
<View style={styles.contentContainer}>
237-
{this.state.columns.map(col =>
236+
{this.state.columns.map(col => (
238237
<VirtualizedList
239238
{...props}
240-
listKey={(item, index) => item.id + index.toString()}
239+
listKey={`$col_${col.index}`}
241240
ref={ref => (this._listRefs[col.index] = ref)}
242241
key={`$col_${col.index}`}
243242
data={col.data}
244243
getItemCount={this._getItemCount}
245244
getItem={this._getItem}
246-
getItemLayout={(data, index) =>
247-
this._getItemLayout(col.index, index)}
248-
renderItem={({ item, index }) =>
249-
renderItem({ item, index, column: col.index })}
245+
getItemLayout={(data, index) => this._getItemLayout(col.index, index)}
246+
renderItem={({ item, index }) => renderItem({ item, index, column: col.index })}
250247
renderScrollComponent={this._renderScrollComponent}
251248
keyExtractor={keyExtractor}
252-
onEndReached={onEndReached}
253-
onEndReachedThreshold={this.props.onEndReachedThreshold}
249+
onEndReached={this._onEndReached}
250+
// onEndReachedThreshold={this.props.onEndReachedThreshold}
254251
removeClippedSubviews={false}
255-
/>,
256-
)}
252+
/>
253+
))}
257254
</View>
258255
);
259256

@@ -271,6 +268,7 @@ export default class MasonryList extends React.Component<Props, State> {
271268
},
272269
headerElement,
273270
emptyElement && this.props.data.length === 0 ? emptyElement : content,
271+
footerElement
274272
);
275273

276274
return scrollComponent;

0 commit comments

Comments
 (0)