Skip to content

Commit 0768958

Browse files
committed
feat: 🎸 add <InfiniteScroll> component
1 parent 16d1603 commit 0768958

File tree

3 files changed

+98
-4
lines changed

3 files changed

+98
-4
lines changed
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import * as React from 'react';
2+
import {storiesOf} from '@storybook/react';
3+
import {InfiniteScroll} from '..';
4+
5+
const h = React.createElement;
6+
7+
const Block = () => {
8+
return <div style={{
9+
width: 100,
10+
height: 100,
11+
margin: 20,
12+
background: 'red',
13+
}}></div>
14+
};
15+
16+
class Demo extends React.Component {
17+
state = {
18+
items: [],
19+
cursor: 1,
20+
};
21+
22+
constructor (props) {
23+
super(props);
24+
this.load();
25+
}
26+
27+
load = (cnt = 5) => {
28+
console.log('loading for cursor: ' + this.state.cursor);
29+
const items = [...this.state.items];
30+
for (let i = 0; i < cnt; i++) {
31+
items.push(<Block key={items.length} />);
32+
}
33+
this.setState({
34+
items,
35+
cursor: this.state.cursor + 1,
36+
});
37+
};
38+
39+
render () {
40+
return (
41+
<InfiniteScroll hasMore={this.state.cursor < 5} loadMore={this.load} cursor={this.state.cursor}>
42+
{this.state.items}
43+
</InfiniteScroll>
44+
);
45+
}
46+
}
47+
48+
storiesOf('UI/InfiniteScroll', module)
49+
// .add('Documentation', () => h(ShowDocs, {md: require('../../../docs/en/Lifecycles.md')}))
50+
.add('Example', () => <Demo />)

src/InfiniteScroll/index.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import * as React from 'react';
2+
import {ViewportSensor} from '../ViewportSensor';
3+
import {ViewportScrollSensor} from '../ViewportScrollSensor';
4+
5+
const h = React.createElement;
6+
const defaultSentinel = h('div', {style: {width: 1, height: 1}});
7+
8+
export interface InfiniteScrollProps {
9+
cursor?: number | string;
10+
sentinel?: React.ReactElement<any>;
11+
hasMore?: boolean;
12+
loadMore: () => void;
13+
}
14+
15+
export interface InfiniteScrollState {
16+
}
17+
18+
export class InfiniteScroll extends React.Component<InfiniteScrollProps, InfiniteScrollProps> {
19+
static defaultProps = {
20+
sentinel: defaultSentinel,
21+
hasMore: true,
22+
};
23+
24+
lastLoadMoreCursor: number | string | null = null;
25+
26+
onViewportChange = ({visible}) => {
27+
if (visible) {
28+
if (this.lastLoadMoreCursor !== this.props.cursor) {
29+
this.lastLoadMoreCursor = this.props.cursor;
30+
this.props.loadMore();
31+
}
32+
}
33+
};
34+
35+
render () {
36+
const {props} = this;
37+
const {children, hasMore, sentinel} = props;
38+
return h(React.Fragment, null,
39+
children,
40+
hasMore &&
41+
h(ViewportScrollSensor, {onChange: this.onViewportChange}, () => sentinel),
42+
);
43+
}
44+
}

src/ViewportScrollSensor/index.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {Component, cloneElement, SFCElement} from 'react';
1+
import * as React from 'react';
22
import {on, off, noop} from '../util';
33
import {throttle} from 'throttle-debounce';
44
import renderProp from '../util/renderProp';
@@ -56,12 +56,12 @@ export interface IViewportScrollSensorState {
5656
visible: boolean;
5757
}
5858

59-
export class ViewportScrollSensor extends Component<IViewportScrollSensorProps, IViewportScrollSensorState> {
59+
export class ViewportScrollSensor extends React.Component<IViewportScrollSensorProps, IViewportScrollSensorState> {
6060
static defaultProps = {
6161
threshold: 0,
6262
throttle: 50,
6363
margin: [0, 0, 0, 0]
64-
};
64+
} as any;
6565

6666
mounted: boolean = false;
6767
el: HTMLElement;
@@ -134,7 +134,7 @@ export class ViewportScrollSensor extends Component<IViewportScrollSensorProps,
134134
}
135135
}
136136

137-
return cloneElement(element, {
137+
return React.cloneElement(element, {
138138
ref: this.ref(element.ref)
139139
});
140140
}

0 commit comments

Comments
 (0)