# 表格滚动加载数据
import React, { useState, useEffect, useRef } from 'react';
import { Table, Space } from 'antd';
const InfiniteScrollTable = () => {
const [dataSource, setDataSource] = useState([]);
const [loading, setLoading] = useState(false);
const [pagination, setPagination] = useState({
current: 1,
pageSize: 10,
total: 0,
});
const tableRef = useRef(null);
const fetchData = async (page, pageSize) => {
try {
setLoading(true);
// 模拟异步请求数据
const response = await fetch(`https://api.example.com/data?page=${page}&pageSize=${pageSize}`);
const data = await response.json();
// 更新数据源和分页信息
setDataSource((prevData) => [...prevData, ...data.dataSource]);
setPagination({
...pagination,
total: data.total,
});
} finally {
setLoading(false);
}
};
const handleScroll = () => {
const tableElement = tableRef.current;
// 当滚动到底部时,加载更多数据
if (tableElement.scrollTop + tableElement.clientHeight === tableElement.scrollHeight) {
const nextPage = pagination.current + 1;
fetchData(nextPage, pagination.pageSize);
setPagination({
...pagination,
current: nextPage,
});
}
};
useEffect(() => {
// 初始化加载第一页数据
fetchData(pagination.current, pagination.pageSize);
}, [pagination.current, pagination.pageSize]);
const columns = [
// 列配置
// ...
];
return (
<div
ref={tableRef}
onScroll={handleScroll}
style={{ height: '400px', overflowY: 'auto' }}
>
<Table
columns={columns}
dataSource={dataSource}
pagination={false} // 禁用默认分页
loading={loading}
/>
</div>
);
};
export default InfiniteScrollTable;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# 使用Intersection Observer API
import React, { useState, useEffect, useRef } from 'react';
import { Table } from 'antd';
const InfiniteScrollTable = () => {
const [dataSource, setDataSource] = useState([]);
const [loading, setLoading] = useState(false);
const [pagination, setPagination] = useState({
current: 1,
pageSize: 10,
total: 0,
});
const bottomObserver = useRef();
const fetchData = async (page, pageSize) => {
try {
setLoading(true);
// 模拟异步请求数据
const response = await fetch(`https://api.example.com/data?page=${page}&pageSize=${pageSize}`);
const data = await response.json();
// 更新数据源和分页信息
setDataSource((prevData) => [...prevData, ...data.dataSource]);
setPagination({
...pagination,
total: data.total,
});
} finally {
setLoading(false);
}
};
const handleIntersection = (entries) => {
const [entry] = entries;
if (entry.isIntersecting) {
// 当底部元素进入视口时加载更多数据
const nextPage = pagination.current + 1;
fetchData(nextPage, pagination.pageSize);
setPagination({
...pagination,
current: nextPage,
});
}
};
useEffect(() => {
// 初始化加载第一页数据
fetchData(pagination.current, pagination.pageSize);
// 创建 Intersection Observer 实例
const observer = new IntersectionObserver(handleIntersection, {
root: null,
rootMargin: '0px',
threshold: 0.1, // 当底部元素可见度达到 10% 时触发回调
});
// 将底部元素添加到观察列表
if (bottomObserver.current) {
observer.observe(bottomObserver.current);
}
// 在组件卸载时断开观察器
return () => observer.disconnect();
}, [pagination.current, pagination.pageSize]);
const columns = [
// 列配置
// ...
];
return (
<div style={{ height: '400px', overflowY: 'auto' }}>
<Table
columns={columns}
dataSource={dataSource}
pagination={false}
loading={loading}
/>
<div ref={bottomObserver} style={{ height: '10px' }} />
</div>
);
};
export default InfiniteScrollTable;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
在这个示例中,我们使用 Intersection Observer 监听了底部元素(bottomObserver)是否进入视口,一旦底部元素进入视口,就触发加载更多数据的逻辑。这样可以更精确地控制何时加载数据,而不是通过滚动事件来判断。