Skip to content

Commit 6c9a921

Browse files
authored
Merge pull request #665 from namespace-ee/layout
performance improvments
2 parents bfc89b6 + a3be1f3 commit 6c9a921

File tree

6 files changed

+107
-52
lines changed

6 files changed

+107
-52
lines changed

CHANGELOG.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,13 @@ and this project adheres (more or less) to [Semantic Versioning](http://semver.o
77

88
## Unreleased
99

10-
# 0.26.4
10+
## 0.26.5
11+
12+
* improve performance by:
13+
- eliminate extra call of layout on state update @ilaiwi
14+
- eliminate unmounting and mounting of Interval Component @ilaiwi
15+
16+
## 0.26.4
1117

1218
* fix `react-calendar-timeline` not working with `react-hot-loader` #607 @ilaiwi + @westn
1319
* add documentation for `stackItems` format #661 @tyson-kubota

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-calendar-timeline",
3-
"version": "0.26.4",
3+
"version": "0.26.5",
44
"description": "react calendar timeline",
55
"main": "lib/index.js",
66
"scripts": {
@@ -95,7 +95,8 @@
9595
"classnames": "^2.2.6",
9696
"create-react-context": "^0.2.2",
9797
"element-resize-detector": "^1.1.12",
98-
"lodash.isequal": "^4.5.0"
98+
"lodash.isequal": "^4.5.0",
99+
"memoize-one": "^5.1.1"
99100
},
100101
"peerDependencies": {
101102
"interactjs": "^1.3.4",

src/lib/Timeline.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -439,7 +439,11 @@ export default class ReactCalendarTimeline extends Component {
439439
(this.state.visibleTimeStart - this.state.canvasTimeStart) /
440440
newZoom
441441
)
442-
const componentScrollLeft = Math.round(this.scrollComponent.scrollLeft)
442+
const componentScrollLeft = Math.round(
443+
prevState.width *
444+
(prevState.visibleTimeStart - prevState.canvasTimeStart) /
445+
oldZoom
446+
)
443447
if (componentScrollLeft !== scrollLeft) {
444448
this.scrollComponent.scrollLeft = scrollLeft
445449
this.scrollHeaderRef.scrollLeft = scrollLeft
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import React from 'react'
2+
import Interval from './Interval'
3+
export function CustomDateHeader({
4+
headerContext: { intervals, unit },
5+
getRootProps,
6+
getIntervalProps,
7+
showPeriod,
8+
data: {
9+
style,
10+
intervalRenderer,
11+
className,
12+
getLabelFormat,
13+
unitProp,
14+
headerData
15+
}
16+
}) {
17+
return (
18+
<div
19+
data-testid={`dateHeader`}
20+
className={className}
21+
{...getRootProps({ style })}
22+
>
23+
{intervals.map(interval => {
24+
const intervalText = getLabelFormat(
25+
[interval.startTime, interval.endTime],
26+
unit,
27+
interval.labelWidth
28+
)
29+
return (
30+
<Interval
31+
key={`label-${interval.startTime.valueOf()}`}
32+
unit={unit}
33+
interval={interval}
34+
showPeriod={showPeriod}
35+
intervalText={intervalText}
36+
primaryHeader={unitProp === 'primaryHeader'}
37+
getIntervalProps={getIntervalProps}
38+
intervalRenderer={intervalRenderer}
39+
headerData={headerData}
40+
/>
41+
)
42+
})}
43+
</div>
44+
)
45+
}

src/lib/headers/DateHeader.js

Lines changed: 42 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ import { TimelineStateConsumer } from '../timeline/TimelineStateContext'
44
import CustomHeader from './CustomHeader'
55
import { getNextUnit } from '../utility/calendar'
66
import { defaultHeaderFormats } from '../default-config'
7-
import Interval from './Interval'
7+
import memoize from 'memoize-one'
8+
import { CustomDateHeader } from './CustomDateHeader'
89

910
class DateHeader extends React.Component {
1011
static propTypes = {
@@ -19,7 +20,7 @@ class DateHeader extends React.Component {
1920
]).isRequired,
2021
intervalRenderer: PropTypes.func,
2122
headerData: PropTypes.object,
22-
height: PropTypes.number,
23+
height: PropTypes.number
2324
}
2425

2526
getHeaderUnit = () => {
@@ -31,14 +32,14 @@ class DateHeader extends React.Component {
3132
return this.props.timelineUnit
3233
}
3334

34-
getRootStyle = () => {
35+
getRootStyle = memoize(style => {
3536
return {
3637
height: 30,
37-
...this.props.style
38+
...style
3839
}
39-
}
40+
})
4041

41-
getLabelFormat(interval, unit, labelWidth) {
42+
getLabelFormat = (interval, unit, labelWidth) => {
4243
const { labelFormat } = this.props
4344
if (typeof labelFormat === 'string') {
4445
const startTime = interval[0]
@@ -50,50 +51,43 @@ class DateHeader extends React.Component {
5051
}
5152
}
5253

54+
getHeaderData = memoize(
55+
(
56+
intervalRenderer,
57+
style,
58+
className,
59+
getLabelFormat,
60+
unitProp,
61+
headerData
62+
) => {
63+
return {
64+
intervalRenderer,
65+
style,
66+
className,
67+
getLabelFormat,
68+
unitProp,
69+
headerData
70+
}
71+
}
72+
)
73+
5374
render() {
5475
const unit = this.getHeaderUnit()
5576
const { headerData, height } = this.props
5677
return (
57-
<CustomHeader unit={unit} height={height} headerData={headerData}>
58-
{({
59-
headerContext: { intervals },
60-
getRootProps,
61-
getIntervalProps,
62-
showPeriod,
63-
data
64-
}) => {
65-
const unit = this.getHeaderUnit()
66-
67-
return (
68-
<div
69-
data-testid={`dateHeader`}
70-
className={this.props.className}
71-
{...getRootProps({ style: this.getRootStyle() })}
72-
>
73-
{intervals.map(interval => {
74-
const intervalText = this.getLabelFormat(
75-
[interval.startTime, interval.endTime],
76-
unit,
77-
interval.labelWidth
78-
)
79-
return (
80-
<Interval
81-
key={`label-${interval.startTime.valueOf()}`}
82-
unit={unit}
83-
interval={interval}
84-
showPeriod={showPeriod}
85-
intervalText={intervalText}
86-
primaryHeader={this.props.unit === 'primaryHeader'}
87-
getIntervalProps={getIntervalProps}
88-
intervalRenderer={this.props.intervalRenderer}
89-
headerData={data}
90-
/>
91-
)
92-
})}
93-
</div>
94-
)
95-
}}
96-
</CustomHeader>
78+
<CustomHeader
79+
unit={unit}
80+
height={height}
81+
headerData={this.getHeaderData(
82+
this.props.intervalRenderer,
83+
this.getRootStyle(this.props.style),
84+
this.props.className,
85+
this.getLabelFormat,
86+
this.props.unit,
87+
this.props.headerData
88+
)}
89+
children={CustomDateHeader}
90+
/>
9791
)
9892
}
9993
}
@@ -105,7 +99,7 @@ const DateHeaderWrapper = ({
10599
className,
106100
intervalRenderer,
107101
headerData,
108-
height,
102+
height
109103
}) => (
110104
<TimelineStateConsumer>
111105
{({ getTimelineState }) => {
@@ -137,7 +131,7 @@ DateHeaderWrapper.propTypes = {
137131
]),
138132
intervalRenderer: PropTypes.func,
139133
headerData: PropTypes.object,
140-
height: PropTypes.number,
134+
height: PropTypes.number
141135
}
142136

143137
DateHeaderWrapper.defaultProps = {

yarn.lock

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5195,6 +5195,11 @@ mem@^4.0.0:
51955195
mimic-fn "^2.0.0"
51965196
p-is-promise "^2.0.0"
51975197

5198+
memoize-one@^5.1.1:
5199+
version "5.1.1"
5200+
resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.1.1.tgz#047b6e3199b508eaec03504de71229b8eb1d75c0"
5201+
integrity sha512-HKeeBpWvqiVJD57ZUAsJNm71eHTykffzcLZVYWiVfQeI1rJtuEaS7hQiEpWfVVk18donPwJEcFKIkCmPJNOhHA==
5202+
51985203
memory-fs@^0.4.0, memory-fs@~0.4.1:
51995204
version "0.4.1"
52005205
resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552"

0 commit comments

Comments
 (0)