diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3e5b5a7d2..cd4a6c1e9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,7 +7,13 @@ and this project adheres (more or less) to [Semantic Versioning](http://semver.o
## Unreleased
-# 0.26.4
+## 0.26.5
+
+* improve performance by:
+ - eliminate extra call of layout on state update @ilaiwi
+ - eliminate unmounting and mounting of Interval Component @ilaiwi
+
+## 0.26.4
* fix `react-calendar-timeline` not working with `react-hot-loader` #607 @ilaiwi + @westn
* add documentation for `stackItems` format #661 @tyson-kubota
diff --git a/package.json b/package.json
index c646eaad5..1398fb5b3 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "react-calendar-timeline",
- "version": "0.26.4",
+ "version": "0.26.5",
"description": "react calendar timeline",
"main": "lib/index.js",
"scripts": {
@@ -95,7 +95,8 @@
"classnames": "^2.2.6",
"create-react-context": "^0.2.2",
"element-resize-detector": "^1.1.12",
- "lodash.isequal": "^4.5.0"
+ "lodash.isequal": "^4.5.0",
+ "memoize-one": "^5.1.1"
},
"peerDependencies": {
"interactjs": "^1.3.4",
diff --git a/src/lib/Timeline.js b/src/lib/Timeline.js
index 571d89c23..f5004cf11 100644
--- a/src/lib/Timeline.js
+++ b/src/lib/Timeline.js
@@ -439,7 +439,11 @@ export default class ReactCalendarTimeline extends Component {
(this.state.visibleTimeStart - this.state.canvasTimeStart) /
newZoom
)
- const componentScrollLeft = Math.round(this.scrollComponent.scrollLeft)
+ const componentScrollLeft = Math.round(
+ prevState.width *
+ (prevState.visibleTimeStart - prevState.canvasTimeStart) /
+ oldZoom
+ )
if (componentScrollLeft !== scrollLeft) {
this.scrollComponent.scrollLeft = scrollLeft
this.scrollHeaderRef.scrollLeft = scrollLeft
diff --git a/src/lib/headers/CustomDateHeader.js b/src/lib/headers/CustomDateHeader.js
new file mode 100644
index 000000000..860f4d411
--- /dev/null
+++ b/src/lib/headers/CustomDateHeader.js
@@ -0,0 +1,45 @@
+import React from 'react'
+import Interval from './Interval'
+export function CustomDateHeader({
+ headerContext: { intervals, unit },
+ getRootProps,
+ getIntervalProps,
+ showPeriod,
+ data: {
+ style,
+ intervalRenderer,
+ className,
+ getLabelFormat,
+ unitProp,
+ headerData
+ }
+}) {
+ return (
+
+ {intervals.map(interval => {
+ const intervalText = getLabelFormat(
+ [interval.startTime, interval.endTime],
+ unit,
+ interval.labelWidth
+ )
+ return (
+
+ )
+ })}
+
+ )
+}
diff --git a/src/lib/headers/DateHeader.js b/src/lib/headers/DateHeader.js
index d3be49834..44191e77a 100644
--- a/src/lib/headers/DateHeader.js
+++ b/src/lib/headers/DateHeader.js
@@ -4,7 +4,8 @@ import { TimelineStateConsumer } from '../timeline/TimelineStateContext'
import CustomHeader from './CustomHeader'
import { getNextUnit } from '../utility/calendar'
import { defaultHeaderFormats } from '../default-config'
-import Interval from './Interval'
+import memoize from 'memoize-one'
+import { CustomDateHeader } from './CustomDateHeader'
class DateHeader extends React.Component {
static propTypes = {
@@ -19,7 +20,7 @@ class DateHeader extends React.Component {
]).isRequired,
intervalRenderer: PropTypes.func,
headerData: PropTypes.object,
- height: PropTypes.number,
+ height: PropTypes.number
}
getHeaderUnit = () => {
@@ -31,14 +32,14 @@ class DateHeader extends React.Component {
return this.props.timelineUnit
}
- getRootStyle = () => {
+ getRootStyle = memoize(style => {
return {
height: 30,
- ...this.props.style
+ ...style
}
- }
+ })
- getLabelFormat(interval, unit, labelWidth) {
+ getLabelFormat = (interval, unit, labelWidth) => {
const { labelFormat } = this.props
if (typeof labelFormat === 'string') {
const startTime = interval[0]
@@ -50,50 +51,43 @@ class DateHeader extends React.Component {
}
}
+ getHeaderData = memoize(
+ (
+ intervalRenderer,
+ style,
+ className,
+ getLabelFormat,
+ unitProp,
+ headerData
+ ) => {
+ return {
+ intervalRenderer,
+ style,
+ className,
+ getLabelFormat,
+ unitProp,
+ headerData
+ }
+ }
+ )
+
render() {
const unit = this.getHeaderUnit()
const { headerData, height } = this.props
return (
-
- {({
- headerContext: { intervals },
- getRootProps,
- getIntervalProps,
- showPeriod,
- data
- }) => {
- const unit = this.getHeaderUnit()
-
- return (
-
- {intervals.map(interval => {
- const intervalText = this.getLabelFormat(
- [interval.startTime, interval.endTime],
- unit,
- interval.labelWidth
- )
- return (
-
- )
- })}
-
- )
- }}
-
+
)
}
}
@@ -105,7 +99,7 @@ const DateHeaderWrapper = ({
className,
intervalRenderer,
headerData,
- height,
+ height
}) => (
{({ getTimelineState }) => {
@@ -137,7 +131,7 @@ DateHeaderWrapper.propTypes = {
]),
intervalRenderer: PropTypes.func,
headerData: PropTypes.object,
- height: PropTypes.number,
+ height: PropTypes.number
}
DateHeaderWrapper.defaultProps = {
diff --git a/yarn.lock b/yarn.lock
index 825082c96..adaeacef0 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -5195,6 +5195,11 @@ mem@^4.0.0:
mimic-fn "^2.0.0"
p-is-promise "^2.0.0"
+memoize-one@^5.1.1:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.1.1.tgz#047b6e3199b508eaec03504de71229b8eb1d75c0"
+ integrity sha512-HKeeBpWvqiVJD57ZUAsJNm71eHTykffzcLZVYWiVfQeI1rJtuEaS7hQiEpWfVVk18donPwJEcFKIkCmPJNOhHA==
+
memory-fs@^0.4.0, memory-fs@~0.4.1:
version "0.4.1"
resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552"