-
Notifications
You must be signed in to change notification settings - Fork 37
/
Copy pathRowPositioner.js
108 lines (94 loc) · 2.88 KB
/
RowPositioner.js
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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
import React from 'react';
import PropTypes from 'prop-types';
class RowPositioner extends React.PureComponent {
static propTypes = {
averageHeight: PropTypes.number,
children: PropTypes.func.isRequired,
gridId: PropTypes.string, // eslint-disable-line
heightCache: PropTypes.object.isRequired,
onPosition: PropTypes.func,
onUnmount: PropTypes.func,
positionCache: PropTypes.object.isRequired,
rowIndex: PropTypes.number.isRequired,
shouldPosition: PropTypes.bool,
}
static defaultProps = {
onPosition: () => {},
onUnmount: () => {},
shouldPosition: true,
}
constructor(props) {
super(props);
const { positionCache, rowIndex, averageHeight, shouldPosition } = props;
let position = null;
if (shouldPosition) {
if (positionCache) {
position = positionCache.request(rowIndex);
}
if (position !== null) {
props.onPosition(position, rowIndex);
}
}
this.state = {
rowIndex,
position,
averageHeight // eslint-disable-line react/no-unused-state
};
}
static getDerivedStateFromProps(props, state) {
const {
rowIndex,
heightCache,
averageHeight,
shouldPosition
} = props;
const newState = {};
if (shouldPosition) {
if ((state.rowIndex !== rowIndex) || (state.averageHeight !== averageHeight)) {
newState.rowIndex = rowIndex;
newState.position = heightCache.requestAccumulated(rowIndex, null);
}
return newState;
}
return null;
}
// if we weren't able to obtain position in the constructor,
// request an accumulated position from the cache of rowHeights.
// we do this after mounting so that a state will exist to be set via a setState call.
componentDidMount() {
const { heightCache, rowIndex, shouldPosition } = this.props;
if (shouldPosition && this.state.position === null) {
heightCache.requestAccumulated(rowIndex, this.cachePosition);
}
}
componentWillUnmount() {
const {
heightCache,
rowIndex
} = this.props;
heightCache.clearAccumRequest(rowIndex);
this.props.onUnmount(this.state.position);
}
// once our top style is calculated, store it in the style cache and apply it to
// our state.
cachePosition = (cacheResult) => {
const { positionCache, rowIndex, onPosition } = this.props;
const { result, estimate } = cacheResult;
if (!estimate) {
// console.log(`storing position of row ${rowIndex}`);
if (positionCache) {
positionCache.set(rowIndex, result);
}
}
if (this.state.position !== result) {
onPosition(cacheResult, rowIndex);
this.setState({ position: result });
}
}
render() {
const { children } = this.props;
const { rowIndex, position } = this.state;
return children({ localRowIndex: rowIndex, rowIndex, position });
}
}
export default RowPositioner;