skip to Main Content

I use react-dropdown-date component to select the date. It works well when the format is the following: year -> month -> day but when I want to change the format for exmaple: day -> month -> year then I got the issue. So, when I set the day and month the day value dissapears, clear out in the dropdown menu.

Code:

import ICustomField from '../../typings/ICostumField';
import React, {useEffect, useState} from 'react';
import {getInstanceError} from '../../utils/getInstanceError';
import {YearPicker, MonthPicker, DayPicker} from 'react-dropdown-date';
import { getUserDate } from '../../utils/utilsDate'; //getCorrectDate, 

const formatDate = (date) => {
  let d = new Date(date),
    day = '' + d.getDate(),
    month = '' + (d.getMonth() + 1),
    year = d.getFullYear();

  if (day.length < 2) day = '0' + day;
  if (month.length < 2) month = '0' + month;

  return [year, month, day].join('-');
}

const CustomField = ({register, errors, name, label, disabled, type = 'text', defaultValue = '', placeholder = '', styles = {}, setError, ...rest}: ICustomField) => {
  const [touch, setTouch] = useState(false);
  const [isOpen, setIsOpen] = useState(false);
  const [touchYear, setTouchYear] = useState(false);
  const [touchMonth, setTouchMonth] = useState(false);
  const [touchDay, setTouchDay] = useState(false);
  const [selectDate, setSelectDate] = useState<any>(null);
  const [year, setYear] = useState<any>();
  const [month, setMonth] = useState<any>();
  const [day, setDay] = useState<any>();
  const minDate = new Date();
  const maxDate = new Date();
  minDate.setFullYear(maxDate.getFullYear() - 100);
  maxDate.setFullYear(maxDate.getFullYear() + 3);

  const {
    getMessageError,
    getClassError
  } = getInstanceError(errors);

  const handelBlur = () => {
    setTouch(true);
  };

  useEffect(() => {
    if (year && month && day) {
      setSelectDate(new Date(year, month, day));
      setIsOpen(false);
    }
  }, [year, month, day]);

  const mes = getMessageError(name);
  if (disabled) return null;
  return (
    <div className={getClassError(name, touch)}>
      <label>{label}</label>
      {type !== 'date' && (
        <input
          name={name}
          ref={register}
          type={type}
          placeholder={placeholder}
          onBlur={handelBlur}
          defaultValue={defaultValue}
          {...rest}
        />
      )}
      {type === 'date' && (
        <>
          <input
            name={name}
            ref={register}
            value={selectDate ? getUserDate(selectDate) : ''}
            onClick={() => setIsOpen(true)}
            onBlur={handelBlur}
            placeholder={placeholder}
            readOnly={true}
          />
          {isOpen &&
            <div className='dateDropDown-container-modal'>
              <div className='dateDropDown-close' onClick={() => setIsOpen(false)}>x</div>
              <DayPicker
                defaultValue={'День'}
                year={year}
                month={month}
                endYearGiven
                required={true}
                value={day}
                onChange={(day) => {
                  setDay(day);
                  setTouchDay(true);
                }}
                id={'day'}
                name={'day'}
                classes={touchDay ? 'dateDropDown-touch' : 'dateDropDown'}
                optionClasses={'dateDropDown-option'}
              />
              <MonthPicker
                defaultValue={'Місяць'}
                numeric
                short
                caps
                endYearGiven
                year={year}
                required={true}
                value={month}
                onChange={(month) => {
                  setMonth(month);
                  setTouchMonth(true);
                }}
                id={'month'}
                name={'month'}
                classes={touchMonth ? 'dateDropDown-touch' : 'dateDropDown'}
                optionClasses={'dateDropDown-option'}
              />
              <YearPicker
                defaultValue={'Рік'}
                start={+formatDate(minDate).split('-')[0]}
                end={+formatDate(maxDate).split('-')[0]}
                reverse
                required={true}
                value={year}
                onChange={(year) => {
                  setYear(year);
                  setTouchYear(true);
                }}
                id={'year'}
                name={'year'}
                classes={touchYear ? 'dateDropDown-touch' : 'dateDropDown'}
                optionClasses={'dateDropDown-option'}
              />
            </div>
          }
        </>
      )}
      {mes && <p>{mes}</p>}
    </div>
  )
};

export default CustomField;

Screenshots:
enter image description here

enter image description here

Any ideas how to fix such issue? Thanks.

2

Answers


  1. Chosen as BEST ANSWER

    When properly debugging, I found out this issue could be releated to this component. Actually, days are calculating by year and month in getDaysInMonth function. So, when React code is translated to JS, I got the following code:

    Code:

    var DayPicker =
    /** @class */
    function (_super) {
      __extends(DayPicker, _super);
    
      function DayPicker() {
        var _this = _super !== null && _super.apply(this, arguments) || this;
    
        _this.renderDayOptions = function () {
          var _a = _this.props,
              month = _a.month,
              year = _a.year,
              endYearGiven = _a.endYearGiven,
              optionClasses = _a.optionClasses,
              defaultValue = _a.defaultValue;
          console.log(year, month);
          var days = month ? getDaysInMonth(year, month) : 31;
          console.log(days);
          var today = new Date();
    

    So, when I pick a day, it sets as 31 and when I pick a month, it sets days as NaN because to calculate days using getDaysInMonth it requires a year and a month as parameters: var days = month ? getDaysInMonth(year, month) : 31;

    That is why it fails for me when I change the order/format to day -> month -> year. So, I decided to switch back to the previous format: year -> month -> day. This issue is resolved. Thank you.


  2. Based on your code, it seems like the issue might be related to how the state is being managed for the day, month, and year values. Since the order of the dropdowns has changed, you need to adjust the state updates accordingly.

    Here’s a modification to your onChange handlers in the DayPicker, MonthPicker, and YearPicker components to handle the change in the new order ("day -> month -> year"):

    // ...
    
    <DayPicker
      // ...
      onChange={(day) => {
        setDay(day);
        setTouchDay(true);
    
        if (month !== undefined && year !== undefined) {
          setSelectDate(new Date(year, month, day));
          setIsOpen(false);
        }
      }}
      // ...
    />
    
    <MonthPicker
      // ...
      onChange={(month) => {
        setMonth(month);
        setTouchMonth(true);
    
        if (day !== undefined && year !== undefined) {
          setSelectDate(new Date(year, month, day));
          setIsOpen(false);
        }
      }}
      // ...
    />
    
    <YearPicker
      // ...
      onChange={(year) => {
        setYear(year);
        setTouchYear(true);
    
        if (day !== undefined && month !== undefined) {
          setSelectDate(new Date(year, month, day));
          setIsOpen(false);
        }
      }}
      // ...
    />
    
    // ...
    
    

    By checking if all three values (day, month, and year) are defined before updating the selectDate and closing the dropdown, you ensure that the date value is correctly updated when changing the format.

    Remember to replace the respective parts of your existing code with these modified onChange handlers.

    Additionally, make sure that the rest of your code, including CSS classes and styling, works well with the new format.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search