Hacker0x01 / react-datepicker

A simple and reusable datepicker component for React
https://reactdatepicker.com/
MIT License
8.07k stars 2.24k forks source link

changeMonth in custom header is inconsistent based on last selected date #3829

Open TravisJRyan opened 1 year ago

TravisJRyan commented 1 year ago

Describe the bug When you use the "changeMonth" function in a custom header, the actual month that gets selected is different dependent on the last date you clicked on. This seems to be happening when you use react-datepicker with monthsShown >= 2.

To Reproduce I copied the below from the example docs ("Custom header with two months displayed" section) with small changes (adding a "Jump to June" button which calls changeMonth(5)). Try the following:

  1. Click on the "Jump to June" button. It changes the display to show June on the left and July on the right. This seems correct.
  2. Then click some day in July and reopen the calendar.
  3. Then click the button again. The display is May on the left and June on the right. It seems react-datepicker is doing some implicit offset that makes it impossible to control which month gets displayed by passing in a target value. Now I'm trying to get June to be on the left by calling changeMonth(5) again but it won't happen. The offset seems to get worse the more calendars I put on the screen.

The only workaround seems to be some hack where I keep track of the last month I clicked and write some offset logic to fix the bug myself.

() => {
  const [startDate, setStartDate] = useState(new Date());
  return (
    <DatePicker
      renderCustomHeader={({
        monthDate,
        customHeaderCount,
        decreaseMonth,
        increaseMonth,
        changeMonth
      }) => (
        <div>
          <button
            aria-label="Previous Month"
            className={
              "react-datepicker__navigation react-datepicker__navigation--previous"
            }
            style={customHeaderCount === 1 ? { visibility: "hidden" } : null}
            onClick={decreaseMonth}
          >
            <span
              className={
                "react-datepicker__navigation-icon react-datepicker__navigation-icon--previous"
              }
            >
              {"<"}
            </span>
          </button>
          <button onClick={() => {changeMonth(5)}}>Jump to June</button>
          <span
          className="react-datepicker__current-month">
            {monthDate.toLocaleString("en-US", {
              month: "long",
              year: "numeric",
            })}
          </span>
          <button
            aria-label="Next Month"
            className={
              "react-datepicker__navigation react-datepicker__navigation--next"
            }
            style={customHeaderCount === 0 ? { visibility: "hidden" } : null}
            onClick={increaseMonth}
          >
            <span
              className={
                "react-datepicker__navigation-icon react-datepicker__navigation-icon--next"
              }
            >
              {">"}
            </span>
          </button>
        </div>
      )}
      selected={startDate}
      onChange={(date) => setStartDate(date)}
      monthsShown={2}
    />
  );
};

Expected behavior Calling changeMonth(5) should always put June on the left. Jumping to a month, when in a sequence of calendars, should have a consistent defintion of what changing a month means.

Screenshots

  1. Open the calendar. datepicker-bug-1
  2. Click the "jump to June" button datepicker-bug-2
  3. Click a day in July datepicker-bug-3
  4. Click the "jump to June" button again. Observe how June is now on the right and not the left, and July is no longer visible. datepicker-bug-4

Desktop (please complete the following information):

Smartphone (please complete the following information):

Additional context N/A

jongjunpark commented 1 year ago

same issue

github-actions[bot] commented 4 months ago

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.