1
- /**
2
- * @class BottomScrollListener
3
- *
4
- * A simple React component that lets you listen for when you have scrolled to the bottom.
5
- *
6
- */
1
+ import React from 'react'
7
2
8
- import debounce from 'lodash.debounce'
9
- import React , { Component } from 'react'
3
+ import useBottomScrollListener , { DebounceOptions } from '../hook'
10
4
11
5
export interface Props {
12
- /** Required callback that will be invoked when scrolled to bottom */
6
+ /**
7
+ * Required callback that will be invoked when scrolled to bottom
8
+ */
13
9
onBottom : ( ) => void
14
10
15
- /** Optional debounce in milliseconds, defaults to 200ms */
16
- debounce : number
11
+ /**
12
+ * Offset from bottom of page in pixels. E.g. 300 will trigger onBottom 300px from the bottom of the page
13
+ */
14
+ offset ?: number
17
15
18
- /** Offset from bottom of page in pixels. E.g. 300 will trigger onBottom 300px from the bottom of the page */
19
- offset : number
16
+ /**
17
+ * Optional debounce in milliseconds, defaults to 200ms
18
+ */
19
+ debounce ?: number
20
+
21
+ /**
22
+ * Options passed to lodash.debounce, see https://lodash.com/docs/4.17.15#debounce
23
+ */
24
+ debounceOptions ?: DebounceOptions
20
25
21
26
/**
22
27
* Optional children to be rendered.
@@ -27,82 +32,21 @@ export interface Props {
27
32
children ?: React . ReactNode | ( < T extends HTMLElement > ( ref : React . Ref < T > ) => React . ReactNode )
28
33
}
29
34
30
- class BottomScrollListener extends Component < Props > {
31
- public static defaultProps = {
32
- debounce : 200 ,
33
- offset : 0 ,
34
- }
35
-
36
- private optionalScrollContainerRef : React . RefObject < HTMLElement > = React . createRef ( )
37
-
38
- public constructor ( props : Props ) {
39
- super ( props )
40
-
41
- if ( props . debounce ) {
42
- this . handleOnScroll = debounce ( this . handleOnScroll . bind ( this ) , props . debounce , { trailing : true } )
43
- } else {
44
- this . handleOnScroll = this . handleOnScroll . bind ( this )
45
- }
46
- }
47
-
48
- public componentDidMount ( ) {
49
- if ( this . props . children instanceof Function ) {
50
- if ( this . optionalScrollContainerRef . current ) {
51
- this . optionalScrollContainerRef . current . addEventListener ( 'scroll' , this . handleOnScroll )
52
- } else {
53
- throw Error (
54
- 'Unable to use scroll container: Ref to child not available, did you pass the ref prop to an element?' ,
55
- )
56
- }
57
- } else {
58
- document . addEventListener ( 'scroll' , this . handleOnScroll )
59
- }
60
- }
61
-
62
- public componentWillUnmount ( ) {
63
- if ( this . props . children instanceof Function ) {
64
- if ( this . optionalScrollContainerRef . current ) {
65
- this . optionalScrollContainerRef . current . removeEventListener ( 'scroll' , this . handleOnScroll )
66
- } else {
67
- throw Error ( 'Unable to clean up scroll container: Ref has been unmounted prematurely.' )
68
- }
69
- } else {
70
- document . removeEventListener ( 'scroll' , this . handleOnScroll )
71
- }
72
- }
73
-
74
- public handleOnScroll ( ) {
75
- if ( this . props . children instanceof Function ) {
76
- const scrollNode = this . optionalScrollContainerRef . current
77
-
78
- if ( scrollNode != null ) {
79
- const scrollContainerBottomPosition = Math . round ( scrollNode . scrollTop + scrollNode . clientHeight )
80
- const scrollPosition = Math . round ( scrollNode . scrollHeight - this . props . offset )
81
-
82
- if ( scrollPosition <= scrollContainerBottomPosition ) {
83
- this . props . onBottom ( )
84
- }
85
- }
86
- } else {
87
- const scrollNode = document . scrollingElement || document . documentElement
88
- const scrollContainerBottomPosition = Math . round ( scrollNode . scrollTop + window . innerHeight )
89
- const scrollPosition = Math . round ( scrollNode . scrollHeight - this . props . offset )
90
-
91
- if ( scrollPosition <= scrollContainerBottomPosition ) {
92
- this . props . onBottom ( )
93
- }
94
- }
95
- }
96
-
97
- public render ( ) {
98
- if ( ! this . props . children ) return null
99
-
100
- if ( this . props . children instanceof Function ) {
101
- return this . props . children ( this . optionalScrollContainerRef )
102
- } else {
103
- return this . props . children
104
- }
105
- }
35
+ /**
36
+ * A simple React component that lets you listen for when you have scrolled to the bottom.
37
+ */
38
+ const BottomScrollListener = ( {
39
+ children,
40
+ onBottom,
41
+ offset,
42
+ debounce,
43
+ debounceOptions,
44
+ } : Props ) : React . ReactNode | null => {
45
+ const optionalScrollContainerRef = useBottomScrollListener ( onBottom , offset , debounce , debounceOptions )
46
+
47
+ if ( ! children ) return null
48
+ else if ( typeof children === 'function' ) return children ( optionalScrollContainerRef )
49
+ else return children
106
50
}
107
51
108
52
export default BottomScrollListener
0 commit comments