react-datepicker icon indicating copy to clipboard operation
react-datepicker copied to clipboard

Using customTimeInput causes input to be very slow & cannot type double digits

Open jennyk1 opened this issue 3 years ago • 1 comments

Describe the bug The main issue is that when I passed my own component into customTimeInput, the component was extremely slow and caused a lot of lag throughout the page (see video below). After doing some digging, we found that this is because we weren't using the onChange and value props that are automatically passed into the custom input component. Instead, we had passed our own versions of these down to support seconds (since seconds are currently not supported).

https://user-images.githubusercontent.com/90651818/189778641-a5268cec-707c-4f23-adb9-28b6ea99c827.mp4

While trying to debug this, we also found that the time input doesn't support typing double digits for the hours and minutes input and this bug can be found in the reactdatepicker.com docs. In the video below, i am trying to type "25". This also happens without the type="time" prop. I believe this is because the onChange method updates the calendar's Date object on every keystroke which causes the built-in time input to lose most of its validation + boundary handling + out-of-the-box time handling.

https://user-images.githubusercontent.com/90651818/189776534-475fb3fd-e7e8-4e12-b329-5eb32386c999.mp4

Expected behavior

  • For the component not to lag when passing our own time input.
  • Support for seconds
  • Able to type double digits in the time input

jennyk1 avatar Sep 12 '22 23:09 jennyk1

The solution/workaround that I found was to turn my TimePickerInput component into a portal and render this through the renderCustomHeader prop.

      <ReactDatePicker
        calendarClassName={pickerClasses}
        customInput={<DatePickerInput Icon={CalendarIcon} {...inputProps} />}
        renderCustomHeader={(
          passedProps: DatePickerHeaderProps
        ): JSX.Element => (
          <>
            <DatePickerHeader {...passedProps} {...headerProps} />
            <TimePicker {...timePickerProps} />
          </>
        )}
        customTimeInput={<div />}
        {...pickerProps}
      />

and inside the TimePicker it looks like this:

import * as React from 'react';
import ReactDOM from 'react-dom';


const TimePicker = React.forwardRef<HTMLInputElement, TimePickerProps>(
  ({ ..restProps }, ref) => {
    ...
    const node = document.getElementsByClassName(
      'react-datepicker-time__input'
    )[0];

   ...
   
    return node
      ? ReactDOM.createPortal(
              <TimePickerInput
                {...inputProps}
                ref={ref}
                // to utilize the built in javascript time input,
                // we dont want to alter how the timestamp is stored
                onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
                  setTimestamp(e.target.value)
                }
                value={timestamp}
              />
          node
        )
      : null;
  }
);

this allowed us to support seconds, eliminate the lag & take advantage of the built in javascript time input

jennyk1 avatar Sep 12 '22 23:09 jennyk1

@jennyk1 For a custom time picker, you use a library or your own time picker code (time picker from first video). If the library can provide the name of this library

tfi-spyro avatar Apr 04 '23 19:04 tfi-spyro

@tfi-spyro it's a regular html input element with custom styles

 <input
            {..._omit(restProps, ['type', 'step'])}
            value={value}
            type="time"
            step="1"
            ref={ref}
          />

jennyk1 avatar Apr 04 '23 19:04 jennyk1

This issue is stale because it has been open 180 days with no activity. Remove stale label or comment or this will be closed in 10 days.

github-actions[bot] avatar Jun 11 '24 01:06 github-actions[bot]