From 91f1ae4f5543696aeb951fd88e33784e3b2039d2 Mon Sep 17 00:00:00 2001 From: Joe Lencioni Date: Wed, 1 Feb 2017 15:30:39 -0800 Subject: [PATCH] Avoid rendering DayPicker when not visible I was looking at some markup that we generate during server rendering and noticed a whole bunch of markup (~32 KiB of HTML) belonging to react-dates for elements that were not visible. With a couple of minor modifications, we can avoid rendering most of these nodes until the input is actually focused and we want to open the DayPicker. This should give us a nice performance boost for both server-rendered pages with this component and again on the client when rendering happens. --- css/DateRangePicker.scss | 8 --- css/SingleDatePicker.scss | 8 --- src/components/DateRangePicker.jsx | 39 ++++++++++----- src/components/SingleDatePicker.jsx | 32 +++++++++--- test/components/DateRangePicker_spec.jsx | 58 +++++++++++++--------- test/components/SingleDatePicker_spec.jsx | 59 +++++++++++------------ 6 files changed, 116 insertions(+), 88 deletions(-) diff --git a/css/DateRangePicker.scss b/css/DateRangePicker.scss index 3cfdaee93d..03059f8f20 100644 --- a/css/DateRangePicker.scss +++ b/css/DateRangePicker.scss @@ -23,14 +23,6 @@ top: $react-dates-spacing-vertical-picker; } -.DateRangePicker__picker--show { - visibility: visible; -} - -.DateRangePicker__picker--invisible { - visibility: hidden; -} - .DateRangePicker__picker--direction-left { left: 0; } diff --git a/css/SingleDatePicker.scss b/css/SingleDatePicker.scss index ffcbf7aaa3..a1d4b79a0e 100644 --- a/css/SingleDatePicker.scss +++ b/css/SingleDatePicker.scss @@ -12,14 +12,6 @@ top: $react-dates-spacing-vertical-picker; } -.SingleDatePicker__picker--show { - visibility: visible; -} - -.SingleDatePicker__picker--invisible { - visibility: hidden; -} - .SingleDatePicker__picker--direction-left { left: 0; } diff --git a/src/components/DateRangePicker.jsx b/src/components/DateRangePicker.jsx index 5344465ed9..06cbaf5569 100644 --- a/src/components/DateRangePicker.jsx +++ b/src/components/DateRangePicker.jsx @@ -92,30 +92,32 @@ export default class DateRangePicker extends React.Component { return shallowCompare(this, nextProps, nextState); } + componentDidUpdate(prevProps) { + if (!prevProps.focusedInput && this.props.focusedInput && this.isOpened()) { + // The date picker just changed from being closed to being open. + this.responsivizePickerPosition(); + } + } + componentWillUnmount() { window.removeEventListener('resize', this.responsivizePickerPosition); } onOutsideClick() { - const { focusedInput, onFocusChange } = this.props; - if (!focusedInput) return; + const { onFocusChange } = this.props; + if (!this.isOpened()) return; onFocusChange(null); } getDayPickerContainerClasses() { const { - focusedInput, orientation, withPortal, withFullScreenPortal, anchorDirection, } = this.props; - const showDatepicker = focusedInput === START_DATE || focusedInput === END_DATE; - const dayPickerClassName = cx('DateRangePicker__picker', { - 'DateRangePicker__picker--show': showDatepicker, - 'DateRangePicker__picker--invisible': !showDatepicker, 'DateRangePicker__picker--direction-left': anchorDirection === ANCHOR_LEFT, 'DateRangePicker__picker--direction-right': anchorDirection === ANCHOR_RIGHT, 'DateRangePicker__picker--horizontal': orientation === HORIZONTAL_ORIENTATION, @@ -131,7 +133,16 @@ export default class DateRangePicker extends React.Component { return ReactDOM.findDOMNode(this.dayPicker); } + isOpened() { + const { focusedInput } = this.props; + return focusedInput === START_DATE || focusedInput === END_DATE; + } + responsivizePickerPosition() { + if (!this.isOpened()) { + return; + } + const { anchorDirection, horizontalMargin, withPortal, withFullScreenPortal } = this.props; const { dayPickerContainerStyles } = this.state; @@ -154,11 +165,15 @@ export default class DateRangePicker extends React.Component { } maybeRenderDayPickerWithPortal() { - const { focusedInput, withPortal, withFullScreenPortal } = this.props; + const { withPortal, withFullScreenPortal } = this.props; + + if (!this.isOpened()) { + return null; + } if (withPortal || withFullScreenPortal) { return ( - + {this.renderDayPicker()} ); @@ -193,7 +208,9 @@ export default class DateRangePicker extends React.Component { } = this.props; const { dayPickerContainerStyles } = this.state; - const onOutsideClick = (!withFullScreenPortal && withPortal) ? this.onOutsideClick : undefined; + const onOutsideClick = (!withFullScreenPortal && withPortal) + ? this.onOutsideClick + : undefined; return (