Skip to content

Commit 7f74579

Browse files
author
Elson Correia
committed
update and expose prop types + update and fix docs
1 parent cce8f7c commit 7f74579

File tree

15 files changed

+309
-158
lines changed

15 files changed

+309
-158
lines changed

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
.idea
22
node_modules
33
lib
4-
.npmignore
54
tools
65
coverage
76
*.tgz

.npmignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
tests
2+
src
3+
documentation
4+
tsconfig.json
5+
jest.config.js
6+
*.tgz

README.md

Lines changed: 13 additions & 12 deletions
Large diffs are not rendered by default.

documentation/Doc.md

Lines changed: 133 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ There are available **shorthands props** just in case you want to make batch upd
2121
- [`group`](https://github.com/beforesemicolon/flatlist-react/blob/master/documentation/Doc.md#grouping)
2222
- [`sort`](https://github.com/beforesemicolon/flatlist-react/blob/master/documentation/Doc.md#sorting)
2323
- [`search`](https://github.com/beforesemicolon/flatlist-react/blob/master/documentation/Doc.md#searching)
24-
- [`paginate`](https://github.com/beforesemicolon/flatlist-react/blob/master/documentation/Doc.md#pagination)
24+
- [`pagination`](https://github.com/beforesemicolon/flatlist-react/blob/master/documentation/Doc.md#pagination)
2525
- [`scrollToTop`](https://github.com/beforesemicolon/flatlist-react/blob/master/documentation/Doc.md#scrolltotop)
2626
- [`display`](https://github.com/beforesemicolon/flatlist-react/blob/master/documentation/Doc.md#styling).
2727

@@ -338,21 +338,42 @@ It is also good to use on lists which user normally dont reach the end anyways s
338338
```
339339

340340
## Pagination
341-
FlatList comes with pagination out of the box. This is specially great for when fetching all the items from api would take long
341+
FlatList comes with pagination out of the box. This is specially great for when fetching all the items from api would take long,
342342
so you start with fetching a small portion and then let the user scroll to the bottom, show the loading indicator while you
343343
fetch some more.
344344

345345
To make it work you need to render `FlatList` inside of a scrolling container with "`overflow: auto`" or "`overflow: scroll`".
346-
If the container wrapping flatlist does not scroll it miss the point of infinite scrolling.
346+
If the container wrapping FlatList does not scroll it misses the point of infinite scrolling.
347347

348-
Pagination props will not work while `renderOnScroll` is being used.
348+
```jsx
349+
<div style={{overflow: "auto", height: "300px"}}>
350+
<FlatList
351+
list={this.props.people}
352+
renderItem={this.renderPerson}
353+
renderWhenEmpty={this.showBlank}
354+
/>
355+
</div>
356+
357+
// --- OR ---
358+
359+
<FlatList
360+
list={this.props.people}
361+
renderItem={this.renderPerson}
362+
renderWhenEmpty={this.showBlank}
363+
wrapperHtmlTag="div"
364+
style={{overflow: "auto", height: "300px"}}
365+
/>
366+
```
367+
368+
Pagination props will not work while `renderOnScroll` is being used. Pagination already renders on scroll.
349369

350370
### hasMoreItems
351371
###### boolean
352372
You start by telling FlatList if there are more items to come with `hasMoreItems` prop. It will then start monitor scrolling
353-
and show loading indicator when the user reaches the end of the list.
373+
activities and the list size to show loading indicator when the user reaches the end of the list and fetching begins.
354374

355-
When you are done fetching the whole list you can set this to "false" and FlatList will know you have the whole list.
375+
When you are done fetching the whole list you can set this to "false" and FlatList will know you have the whole list
376+
and stop monitoring scrolling and list size.
356377

357378
### loadMoreItems
358379
###### () => void
@@ -412,7 +433,7 @@ fetchData = () => {
412433
list={this.props.people}
413434
renderItem={this.renderPerson}
414435
renderWhenEmpty={this.showBlank} // let user know if initial data is loading or there is no data to show
415-
paginate={{
436+
pagination={{
416437
hasMore: this.state.hasMoreItems,
417438
loadMore: this.fetchData
418439
}}
@@ -441,7 +462,7 @@ to show while items are being fetched.
441462
list={this.props.people}
442463
renderItem={this.renderPerson}
443464
renderWhenEmpty={this.showBlank} // let user know if initial data is loading or there is no data to show
444-
paginate={{
465+
pagination={{
445466
hasMore: this.state.hasMoreItems,
446467
loadMore: this.fetchData,
447468
loadingIndicator: <div style={{background: '#090'}}>Getting more items...</div>
@@ -470,7 +491,7 @@ you can also specify **"center"** or **"right"**.
470491
list={this.props.people}
471492
renderItem={this.renderPerson}
472493
renderWhenEmpty={this.showBlank} // let user know if initial data is loading or there is no data to show
473-
paginate={{
494+
pagination={{
474495
hasMore: this.state.hasMoreItems,
475496
loadMore: this.fetchData,
476497
loadingIndicator: <div style={{background: '#090'}}>Getting more items...</div>,
@@ -1456,6 +1477,109 @@ The position is where you want the button to be placed. The default is **"bottom
14561477
/>
14571478
```
14581479

1480+
## Utilities
1481+
You may also use the internal utility functions FlatList uses to do all the amazing thing without rendering
1482+
anything or be in React. You may use these to craft your own FlatList alternative, custom to you.
1483+
1484+
### sortList
1485+
###### <T>(list: T[], options?: SortOptionsInterface) => T[]
1486+
1487+
```ts
1488+
import {sortList} from "flatlist-react";
1489+
1490+
const list = [2, 4, 1, 9]
1491+
1492+
sortList(list);
1493+
sortList(list, {descending: true, caseInsensitive: true});
1494+
1495+
const objectArray = [
1496+
{name: 'Last', other: 'Zer', age: 2},
1497+
{name: 'First', other: 'Last', age: 8},
1498+
{name: 'Middle', other: 'Zer', age: 1},
1499+
{name: 'First', other: 'Middle', age: 8},
1500+
{name: 'Last', other: 'Abo', age: 2}
1501+
];
1502+
1503+
sortList(objectArray, {descending: true, caseInsensitive: true, by: 'name'});
1504+
sortList(objectArray, {descending: false, caseInsensitive: true, by: ['name', {key: 'age', descending: true}]});
1505+
```
1506+
1507+
### searchList
1508+
###### <T>(list: T[], options: SearchOptionsInterface) => T[]
1509+
1510+
```ts
1511+
import {searchList} from "flatlist-react";
1512+
1513+
const objectArray = [
1514+
{name: 'Last', other: 'Zer', age: 2},
1515+
{name: 'First', other: 'Last', age: 8},
1516+
{name: 'Middle', other: 'Zer', age: 1},
1517+
{name: 'First', other: 'Middle', age: 8},
1518+
{name: 'Last', other: 'Abo', age: 2}
1519+
];
1520+
1521+
searchList(objectArray, {
1522+
by: ['name', 'other'],
1523+
term: 'Last', // <- search term
1524+
everyWord: false,
1525+
caseInsensitive: true
1526+
})
1527+
```
1528+
1529+
### filterList
1530+
###### <T>(list: T[], by?: ((item: T, idx: number) => boolean) | string) => T[]
1531+
1532+
```ts
1533+
import {filterList} from "flatlist-react";
1534+
1535+
const objectList = [
1536+
{name: 'Last', other: 'Zer', age: 2},
1537+
{name: 'First', other: 'Last', age: 8},
1538+
{name: 'Middle', other: 'Zer', age: 1},
1539+
{name: 'First', other: 'Middle', age: 8},
1540+
{name: 'Last', other: 'Abo', age: 2}
1541+
];
1542+
1543+
filterList(objectList, (item: any) => item.age && item.age > 10);
1544+
filterList(objectList, 'age')
1545+
```
1546+
1547+
### groupList
1548+
###### <T>(list: T[], options?: GroupOptionsInterface) => {groupLabels: string[], groupLists: T[]}
1549+
1550+
```ts
1551+
import {groupList} from "flatlist-react";
1552+
1553+
const objectList = [
1554+
{name: 'Last', other: 'Zer', age: 2},
1555+
{name: 'First', other: 'Last', age: 8},
1556+
{name: 'Middle', other: 'Zer', age: 1},
1557+
{name: 'First', other: 'Middle', age: 7},
1558+
{name: 'Last', other: 'Abo', age: 3}
1559+
];
1560+
1561+
groupList(objectList, {limit: 2});
1562+
1563+
const groupBy: (item: any, idx: number) => string | number = (item: any) => {
1564+
return item.age % 2 === 0 ? 'divided by 2' : 'not divided by 2';
1565+
};
1566+
1567+
groupList(list, {by: groupBy});
1568+
```
1569+
1570+
### limitList
1571+
###### <T>(list: T[], limit?: string | number, to?: string | number) => T[]
1572+
1573+
```ts
1574+
import {limitList} from "flatlist-react";
1575+
1576+
const list = [2, 4, 1, 9, 89, 1, 33]
1577+
1578+
limitList(list, 5) // [2, 4, 1, 9, 89]
1579+
limitList(list, 2, 4) // [3, 4]
1580+
limitList(list, 2, -2) // [3]
1581+
```
1582+
14591583
### Thank You
14601584
Please show your support, help make this better, suggest features, report bugs and even contribute to this
14611585
project.

src/___subComponents/DisplayHandler.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ import { bool, shape, string } from "prop-types";
22
import React, { createRef, useEffect, useState } from "react";
33

44
export interface DisplayInterface {
5-
row: boolean;
6-
rowGap: string;
7-
grid: boolean;
8-
gridGap: string;
9-
gridMinColumnWidth: string;
5+
row?: boolean;
6+
rowGap?: string;
7+
grid?: boolean;
8+
gridGap?: string;
9+
gridMinColumnWidth?: string;
1010
}
1111

1212
export interface DisplayHandlerProps {

src/___subComponents/InfiniteLoader.tsx

Lines changed: 36 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,19 @@
11
import React, { Component, createRef, CSSProperties, ReactNode } from "react";
2-
import { bool, element, func, node, oneOf, oneOfType } from "prop-types";
2+
import {
3+
bool,
4+
element,
5+
func,
6+
node,
7+
oneOf,
8+
oneOfType,
9+
number,
10+
} from "prop-types";
311
import { isFunction } from "../___utils/isType";
412
import DefaultLoadIndicator from "./DefaultLoadIndicator";
513

6-
export interface InfiniteLoaderProps {
7-
loadingIndicator: null | (() => ReactNode) | ReactNode;
8-
loadingIndicatorPosition: string;
14+
export interface InfiniteLoaderInterface {
15+
loadingIndicator?: null | (() => ReactNode) | ReactNode;
16+
loadingIndicatorPosition?: string;
917
hasMore: boolean;
1018
loadMore: null | (() => void);
1119
}
@@ -14,10 +22,16 @@ interface State {
1422
scrollingContainer: HTMLElement | null;
1523
loadIndicatorContainer: HTMLDivElement | null;
1624
loading: boolean;
25+
prevItemsCount: number;
26+
}
27+
28+
interface InfiniteLoaderProps extends InfiniteLoaderInterface {
29+
itemsCount: number;
1730
}
1831

1932
class InfiniteLoader extends Component<InfiniteLoaderProps, State> {
2033
static propTypes = {
34+
itemsCount: number,
2135
hasMore: bool.isRequired,
2236
loadMore: func.isRequired,
2337
loadingIndicator: oneOfType([func, node, element]),
@@ -30,6 +44,7 @@ class InfiniteLoader extends Component<InfiniteLoaderProps, State> {
3044
};
3145

3246
state: State = {
47+
prevItemsCount: this.props.itemsCount,
3348
loadIndicatorContainer: null,
3449
loading: false,
3550
scrollingContainer: null,
@@ -76,7 +91,7 @@ class InfiniteLoader extends Component<InfiniteLoaderProps, State> {
7691

7792
// if prev and current loading are the same is because the component updated from props change
7893
// otherwise is because the component updated itself
79-
if (prevState.loading === this.state.loading) {
94+
if (prevProps.itemsCount !== this.props.itemsCount) {
8095
this.reset();
8196
}
8297
}
@@ -88,11 +103,9 @@ class InfiniteLoader extends Component<InfiniteLoaderProps, State> {
88103

89104
// update the loading flags and items count whether "hasMore" is false or list changed
90105
reset(): void {
91-
if (this.state.loading) {
92-
this.setState({ loading: false });
93-
}
94-
95-
this.checkIfLoadingIsNeeded();
106+
this.setState({ loading: false }, () => {
107+
this.checkIfLoadingIsNeeded();
108+
});
96109
}
97110

98111
getScrollingContainerChildrenCount = (): number => {
@@ -110,13 +123,13 @@ class InfiniteLoader extends Component<InfiniteLoaderProps, State> {
110123

111124
if (scrollingContainer) {
112125
["scroll", "mousewheel", "touchmove"].forEach((event: string) => {
113-
if (removeEvent) {
114-
scrollingContainer.removeEventListener(
115-
event,
116-
this.checkIfLoadingIsNeeded,
117-
true
118-
);
119-
} else {
126+
scrollingContainer.removeEventListener(
127+
event,
128+
this.checkIfLoadingIsNeeded,
129+
true
130+
);
131+
132+
if (!removeEvent) {
120133
scrollingContainer.addEventListener(
121134
event,
122135
this.checkIfLoadingIsNeeded,
@@ -143,7 +156,12 @@ class InfiniteLoader extends Component<InfiniteLoaderProps, State> {
143156
const startingPoint = offsetTop + offsetHeight;
144157

145158
if (loaderPosition <= startingPoint) {
146-
this.setState({ loading: true }, this.props.loadMore as () => void);
159+
this.setState(
160+
{ prevItemsCount: this.props.itemsCount, loading: true },
161+
() => {
162+
(this.props.loadMore as () => void)();
163+
}
164+
);
147165
}
148166
}
149167
};

src/___subComponents/PlainList.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@ import { array, bool, func, node, object, oneOfType, string } from "prop-types";
22
import React, { forwardRef, Ref } from "react";
33
import convertListToArray from "../___utils/convertListToArray";
44
import { isString } from "../___utils/isType";
5-
import { listItem } from "../props";
5+
import { listItem } from "../flatListProps";
66
import DefaultBlank from "./DefaultBlank";
77
import ScrollRenderer from "./ScrollRenderer";
88
import { handleRenderItem, renderBlank, renderFunc } from "./uiFunctions";
99

10-
interface Props {
10+
export interface PlainListProps {
1111
list: listItem[];
1212
renderItem: JSX.Element | renderFunc;
1313
renderWhenEmpty?: null | (() => JSX.Element);
@@ -17,7 +17,7 @@ interface Props {
1717
[key: string]: any;
1818
}
1919

20-
function PlainList(props: Props) {
20+
function PlainList(props: PlainListProps) {
2121
const {
2222
list,
2323
renderItem,
@@ -41,7 +41,7 @@ function PlainList(props: Props) {
4141
{renderOnScroll ? (
4242
<ScrollRenderer list={dataList} renderItem={renderItem} />
4343
) : (
44-
dataList.map(handleRenderItem(renderItem))
44+
dataList.map(handleRenderItem(renderItem) as renderFunc)
4545
)}
4646
</>
4747
);
@@ -88,6 +88,6 @@ PlainList.defaultProps = {
8888
forwardRef: { current: null },
8989
};
9090

91-
export default forwardRef((props: Props, ref: Ref<HTMLElement>) => (
91+
export default forwardRef((props: PlainListProps, ref: Ref<HTMLElement>) => (
9292
<PlainList forwardRef={ref} {...props} />
9393
));

0 commit comments

Comments
 (0)