Skip to content

Commit 280f418

Browse files
authored
Merge pull request #11 from jason89521/clone-element
Clone element
2 parents 0d114aa + de5eea5 commit 280f418

File tree

11 files changed

+102
-173
lines changed

11 files changed

+102
-173
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# React Infinite Scroll Component
22

33
[![npm (scoped)](https://img.shields.io/npm/v/@yuxuan-zheng/react-infinite-scroll)](https://www.npmjs.com/package/@yuxuan-zheng/react-infinite-scroll)
4-
[![npm](https://img.shields.io/npm/dm/@yuxuan-zheng/react-infinite-scroll)](https://www.npmjs.com/package/@yuxuan-zheng/react-infinite-scroll)
4+
[![npm](https://img.shields.io/npm/dt/@yuxuan-zheng/react-infinite-scroll)](https://www.npmjs.com/package/@yuxuan-zheng/react-infinite-scroll)
55
[![npm bundle size (scoped)](https://img.shields.io/bundlephobia/min/@yuxuan-zheng/react-infinite-scroll)](https://www.npmjs.com/package/@yuxuan-zheng/react-infinite-scroll)
66

77
A lightweight package provides a react component that implements the functionality of infinitely scrolling.

docs/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ title: Introduction
99

1010
## Easy to use
1111

12-
To make `InfiniteScroll` work, you just need to tell it whether your application is loading and are there more data to load, then create your `Item` component with `React.forwardRef` and an array with a specific type. Finally, pass a function which should be called when the last item displayed in the viewport.
12+
To make `InfiniteScroll` work, you just need to tell it whether your application is loading, whether there are more data and the function you want to call when it reach bottom
1313

1414
## No pollution
1515

docs/api/InfiniteScroll.md

Lines changed: 10 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -8,34 +8,27 @@ InfiniteScroll is a React component which uses IntersectionObserver to implement
88
## Parameters
99

1010
```tsx
11-
interface Data<T> {
12-
key?: React.Key;
13-
props: T;
14-
}
15-
16-
interface Props<T, P extends HTMLElement> {
11+
interface Props {
1712
isLoading: boolean;
1813
hasMore: boolean;
19-
Item: React.ForwardRefExoticComponent<T & React.RefAttributes<P>> | string;
20-
itemData: Data<T>[];
2114
next: () => unknown;
2215
threshold?: number;
23-
root?: Element | Document | undefined | null;
16+
root?: Element | Document | null;
2417
rootMargin?: string;
2518
reverse?: boolean;
19+
children?: JSX.Element[];
2620
}
2721

28-
declare function InfiniteScroll<T, P extends HTMLElement>({
22+
declare function InfiniteScroll({
2923
isLoading,
3024
hasMore,
31-
Item,
32-
itemData,
3325
next,
3426
threshold,
3527
root,
3628
rootMargin,
3729
reverse,
38-
}: Props<T, P>): JSX.Element;
30+
children,
31+
}: Props): JSX.Element;
3932
```
4033

4134
### `isLoading`
@@ -46,24 +39,6 @@ declare function InfiniteScroll<T, P extends HTMLElement>({
4639

4740
Used to determine whether there are more items to display. If the last item is displayed in the viewport and `hasMore` is `true`, then `InfiniteScroll` will call `next()`.
4841

49-
### `Item`
50-
51-
A React component with `React.forwardedRef` or a string like `li`. `InfiniteScroll` will pass a callback function to the last item's ref in order to determine whether the last item is displayed in the viewport.
52-
53-
### `itemData`
54-
55-
An array of objects. The object in this array has 2 properties called `key` and `props`.
56-
57-
#### `key`
58-
59-
Since `InfiniteScroll` will use `map()` to generate the `Item` component, it needs a key to help React distinguish between components. If the items in `InfiniteScroll` will be deleted or moved, then you should specify a key.
60-
61-
If `key` is not specified, then `InfiniteScroll` will use the index as a key.
62-
63-
#### `props`
64-
65-
The properties that will be passed to `Item` component. Its type should be the same as `Item`'s props.
66-
6742
### `next`
6843

6944
If `isLoading` is `false` and `hasMore` is `true`, then this function will be called when this last item is displayed in the viewport.
@@ -97,3 +72,7 @@ Set this property to `true` means that `InfiniteScroll` will call `next` when th
9772
If your `next` function prepend the new data to the previous data, the first item will always show up on the top. This will cause `InfiniteScroll` continuously call `next`. Make sure write some code to prevent this circumstance or use [`useScrollToOld`](./useScrollToOld.md);
9873

9974
:::
75+
76+
### `children`
77+
78+
`InfiniteScroll` will pass ref to your children, if your children is a custom component, make sure using `React.forwardRef` to forward ref to its container.

docs/api/useScrollToOld.md

Lines changed: 11 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -54,32 +54,22 @@ function ReverseExample() {
5454
setData([...initData].reverse());
5555
if (!containerRef.current) return;
5656
const scrollTop = containerRef.current.scrollHeight - containerRef.current.clientHeight;
57-
containerRef.current.scrollTo({ top: scrollTop });
57+
containerRef.current?.scrollTo({ top: scrollTop });
5858
});
5959
}, []);
6060

61-
const itemData = data.map(datum => {
62-
const key = datum.id;
63-
const props: ListItemProps = {
64-
id: datum.id,
65-
title: datum.title,
66-
children: <div>I am a JSX element</div>,
67-
};
68-
return { key, props };
69-
});
70-
7161
return (
7262
<ul ref={containerRef}>
73-
<InfiniteScroll
74-
isLoading={isLoading}
75-
hasMore={true}
76-
itemData={itemData}
77-
Item={ListItem}
78-
next={next}
79-
threshold={1}
80-
reverse
81-
/>
63+
<InfiniteScroll isLoading={isLoading} hasMore={true} next={next} threshold={1} reverse>
64+
{data.map(datum => {
65+
return (
66+
<ListItem key={datum.id} title={datum.title} id={datum.id}>
67+
<div>I am a JSX element</div>
68+
</ListItem>
69+
);
70+
})}
71+
</InfiniteScroll>
8272
</ul>
8373
);
8474
}
85-
```
75+
```

docs/getting-started.md

Lines changed: 22 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -14,44 +14,17 @@ yarn add @yuxuan-zheng/react-infinite-scroll
1414
npm install @yuxuan-zheng/react-infinite-scroll
1515
```
1616

17-
## Create your `Item` component
18-
19-
To use React Infinite Scroll, you need to create a custom `Item` component and then pass a `React.ForwardedRef` to its container.
20-
21-
```tsx
22-
export interface ItemProps {
23-
id: number;
24-
prop1: string;
25-
prop2: string;
26-
prop3: number;
27-
}
28-
29-
function Item(props: ItemProps, ref: React.FowardedRef<HTMLLIElement>) {
30-
return <li ref={ref}>{props.data}</li>;
31-
}
32-
33-
export default React.forwardRef(Item);
34-
```
35-
36-
:::note
37-
38-
You should make sure that your `Item` component pass ref to its container element, otherwise React Infinite Scroll will not work properly.
39-
40-
:::
41-
4217
## Create a component with `InfiniteScroll`
4318

4419
```tsx
45-
import InfiniteScroll from 'InfiniteScroll';
46-
import Item, { ItemProps } from 'components/Item';
20+
import InfiniteScroll from '@yuxuan-zheng/react-infinite-scroll';
4721

4822
function InfiniteList() {
49-
const [data, setData] = useState<ItemProps>([]);
23+
const [data, setData] = useState([]);
5024
const [isLoading, setIsLoading] = useState(false);
5125
const [page, setpage] = useState(0);
5226

5327
useEffect(() => {
54-
// the return type of fakeApi is Promise<ItemProps[]>
5528
fakeApi(page).then(initData => {
5629
setData(initData);
5730
setPage(page + 1);
@@ -66,23 +39,30 @@ function InfiniteList() {
6639
setIsLoading(false);
6740
};
6841

69-
const itemData = data.map(datum => ({
70-
key: datum.id,
71-
props: datum,
72-
}));
73-
7442
return (
7543
<ul>
76-
<InfiniteScroll
77-
isLoading={isLoading}
78-
hasMore={true}
79-
Item={Item}
80-
itemData={itemData}
81-
next={fetchNext}
82-
/>
44+
<InfiniteScroll isLoading={isLoading} hasMore={page < 3} next={fetchNext}>
45+
{data.map(datum => {
46+
return <li key={datum.id}>Hello</li>;
47+
})}
48+
</InfiniteScroll>
8349
</ul>
8450
);
8551
}
8652
```
8753

88-
The 5 properties in the above example are required. For more information about these properties, please see the [API Reference page.](api/InfiniteScroll.md)
54+
## Create your `Item` component
55+
56+
You can also use a custom component in `InfiniteScroll`, but you should make sure the component pass `ref` to its container correctly.
57+
58+
```tsx
59+
export interface ItemProps {
60+
data: any;
61+
}
62+
63+
function Item(props: ItemProps, ref: React.FowardedRef<HTMLLIElement>) {
64+
return <li ref={ref}>{props.data}</li>;
65+
}
66+
67+
export default React.forwardRef(Item);
68+
```

src/demo/App.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ import ReverseExample from 'components/ReverseExample';
55
function App() {
66
return (
77
<div>
8-
<ReverseExample />
8+
{/* <ReverseExample /> */}
9+
<BasicExample />
910
</div>
1011
);
1112
}

src/demo/components/BasicExample.tsx

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React, { useState, useEffect } from 'react';
2-
import ListItem, { ListItemProps } from './ListItem';
2+
import ListItem from './ListItem';
33
import InfiniteScroll from 'InfiniteScroll';
44
import fakeApi, { Data } from 'fakeApi';
55
import 'index.css';
@@ -23,25 +23,17 @@ function BasicExample() {
2323
});
2424
}, []);
2525

26-
const itemData = data.map(datum => {
27-
const key = datum.id;
28-
const props: ListItemProps = {
29-
id: datum.id,
30-
title: datum.title,
31-
children: <div>I am a JSX element</div>,
32-
};
33-
return { key, props };
34-
});
35-
3626
return (
3727
<ul>
38-
<InfiniteScroll
39-
isLoading={isLoading}
40-
hasMore={page < 3}
41-
itemData={itemData}
42-
Item={ListItem}
43-
next={next}
44-
/>
28+
<InfiniteScroll isLoading={isLoading} hasMore={page < 3} next={next}>
29+
{data.map(datum => {
30+
return (
31+
<ListItem key={datum.id} title={datum.title} id={datum.id}>
32+
<div>I am a JSX element</div>
33+
</ListItem>
34+
);
35+
})}
36+
</InfiniteScroll>
4537
</ul>
4638
);
4739
}

src/demo/components/ReverseExample.tsx

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React, { useState, useEffect, useRef } from 'react';
2-
import ListItem, { ListItemProps } from './ListItem';
2+
import ListItem from './ListItem';
33
import InfiniteScroll, { useScrollToOld } from 'InfiniteScroll';
44
import fakeApi, { Data } from 'fakeApi';
55
import 'index.css';
@@ -31,27 +31,17 @@ function ReverseExample() {
3131
});
3232
}, []);
3333

34-
const itemData = data.map(datum => {
35-
const key = datum.id;
36-
const props: ListItemProps = {
37-
id: datum.id,
38-
title: datum.title,
39-
children: <div>I am a JSX element</div>,
40-
};
41-
return { key, props };
42-
});
43-
4434
return (
4535
<ul ref={containerRef}>
46-
<InfiniteScroll
47-
isLoading={isLoading}
48-
hasMore={true}
49-
itemData={itemData}
50-
Item={ListItem}
51-
next={next}
52-
threshold={1}
53-
reverse
54-
/>
36+
<InfiniteScroll isLoading={isLoading} hasMore={true} next={next} threshold={1} reverse>
37+
{data.map(datum => {
38+
return (
39+
<ListItem key={datum.id} title={datum.title} id={datum.id}>
40+
<div>I am a JSX element</div>
41+
</ListItem>
42+
);
43+
})}
44+
</InfiniteScroll>
5545
</ul>
5646
);
5747
}

src/demo/components/ThresholdExample.tsx

Lines changed: 10 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React, { useState, useEffect } from 'react';
2-
import ListItem, { ListItemProps } from './ListItem';
2+
import ListItem from './ListItem';
33
import InfiniteScroll from 'InfiniteScroll';
44
import fakeApi, { Data } from 'fakeApi';
55
import 'index.css';
@@ -27,26 +27,17 @@ function ThresholdExample({ threshold }: Props) {
2727
});
2828
}, []);
2929

30-
const itemData = data.map(datum => {
31-
const key = datum.id;
32-
const props: ListItemProps = {
33-
id: datum.id,
34-
title: datum.title,
35-
children: <div>I am a JSX element</div>,
36-
};
37-
return { key, props };
38-
});
39-
4030
return (
4131
<ul>
42-
<InfiniteScroll
43-
isLoading={isLoading}
44-
hasMore={page < 3}
45-
itemData={itemData}
46-
Item={ListItem}
47-
next={next}
48-
threshold={threshold}
49-
/>
32+
<InfiniteScroll isLoading={isLoading} hasMore={page < 3} next={next} threshold={threshold}>
33+
{data.map(datum => {
34+
return (
35+
<ListItem key={datum.id} title={datum.title} id={datum.id}>
36+
<div>I am a JSX element</div>
37+
</ListItem>
38+
);
39+
})}
40+
</InfiniteScroll>
5041
</ul>
5142
);
5243
}

0 commit comments

Comments
 (0)