-
-
Notifications
You must be signed in to change notification settings - Fork 132
/
Copy pathuseTableRows.ts
82 lines (70 loc) · 2.51 KB
/
useTableRows.ts
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
import { useState, useCallback, useRef } from 'react';
import getHeight from 'dom-lib/getHeight';
import useUpdateLayoutEffect from './useUpdateLayoutEffect';
import useMount from './useMount';
import isEmpty from 'lodash/isEmpty';
import { RowDataType } from '../@types/common';
import defer from './defer';
interface TableRowsProps<Row, Key> {
prefix: (str: string) => string;
wordWrap?: boolean | 'break-all' | 'break-word' | 'keep-all';
data: readonly Row[];
expandedRowKeys: readonly Key[];
}
/**
* The row information of the table, get the DOM of all rows, and summarize the row height.
* @param props
* @returns
*/
const useTableRows = <Row extends RowDataType, Key>(props: TableRowsProps<Row, Key>) => {
const { prefix, wordWrap, data, expandedRowKeys } = props;
const [tableRowsMaxHeight, setTableRowsMaxHeight] = useState<number[]>([]);
const tableRows = useRef<{ [key: string]: [HTMLElement, any] }>({});
const bindTableRowsRef = (index: number | string, rowData: any) => (ref: HTMLElement) => {
if (ref) {
tableRows.current[index] = [ref, rowData];
}
};
const calculateRowMaxHeight = useCallback(() => {
if (wordWrap) {
const nextTableRowsMaxHeight: number[] = [];
const curTableRows = Object.values(tableRows.current);
for (let i = 0; i < curTableRows.length; i++) {
const [row] = curTableRows[i];
if (row) {
const cells = row.querySelectorAll(`.${prefix('cell-wrap')}`) || [];
const cellArray = Array.from(cells);
let maxHeight = 0;
for (let j = 0; j < cellArray.length; j++) {
const cell = cellArray[j];
const h = getHeight(cell);
maxHeight = Math.max(maxHeight, h);
}
nextTableRowsMaxHeight.push(maxHeight);
}
}
// Can't perform a React state update on an unmounted component
if (!isEmpty(tableRows.current)) {
setTableRowsMaxHeight(nextTableRowsMaxHeight);
}
}
}, [prefix, wordWrap]);
useMount(() => {
defer(calculateRowMaxHeight);
});
useUpdateLayoutEffect(() => {
/**
* After the data is updated, the height of the cell DOM needs to be re-acquired,
* and what is often obtained is not the latest DOM that has been rendered.
* So use `defer` to delay obtaining the height of the cell DOM.
* TODO: To be improved
*/
defer(calculateRowMaxHeight);
}, [data, expandedRowKeys]);
return {
bindTableRowsRef,
tableRowsMaxHeight,
tableRows
};
};
export default useTableRows;