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"