Search code examples
reactjsmaterial-uidatepicker

MUI-X DatePicker: onDaySelect/onChange does not return date of provided type


I want to create a DatePicker with which I can select multiple days.... (no range)

For this purpose I use the MUI-X DatePicker. The date I pass to it is a (Luxon) DateTime.

But the method 'onDaySelect' doesn't give me a "DateTime" (see console output).

This causes the 'isDaySelected' method to throw an error because the value in the array is not a 'DateTime' - and thus does not have a 'hasSame' method.

Have I forgotten anything here? - or could this be a bug in the MUI-X DatePicker?

(GitHub-Repo: https://github.com/emaarco/mui-date-picker-test)

Component

import React, {useCallback, useState} from "react";
import {LocalizationProvider} from "@mui/x-date-pickers/LocalizationProvider";
import {AdapterDateFns} from "@mui/x-date-pickers/AdapterDateFns";
import {PickersDay, StaticDatePicker} from "@mui/x-date-pickers";
import {Badge, TextField} from "@mui/material";
import {DateTime} from "luxon";

const SelectMultipleDates: React.FC = () => {

    const [selectedDates, setSelectedDates] = useState<DateTime[]>([]);

    const handleClickOnDay = useCallback((day: DateTime) => {
        console.log("is dateTime: " + (day instanceof DateTime));
        console.log("is Date: " + (day instanceof Date));
        setSelectedDates([...selectedDates, day]);
    }, [selectedDates]);

    const isDaySelected = useCallback((providedDay: DateTime) => {
        return selectedDates.some((value) => value.hasSame(providedDay, "day"));
    }, [selectedDates]);

    return (
        <LocalizationProvider dateAdapter={AdapterDateFns}>
            <StaticDatePicker
                displayStaticWrapperAs="desktop"
                openTo="day"
                value={DateTime.now()}
                onChange={() => console.log("nothing")}
                renderDay={(day: DateTime) => (
                    <PickersDay 
                        key={day.toString()}
                        day={day}
                        selected={isDaySelected(day)}
                        onDaySelect={(day: DateTime) => handleClickOnDay(day)}
                        outsideCurrentMonth={false}/>
                )}
                closeOnSelect={false}
                renderInput={(params) => <TextField {...params} />}
            />
        </LocalizationProvider>
    );
};

export default SelectMultipleDates;
 

Console output

is dateTime: false       SelectMultipleDates.tsx:13 
is Date: true            SelectMultipleDates.tsx:14

My package.json

{
  "name": "mui-date-picker-test",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@date-io/date-fns": "^2.14.0",
    "@emotion/react": "^11.9.3",
    "@emotion/styled": "^11.9.3",
    "@mui/material": "^5.9.2",
    "@mui/x-date-pickers": "^5.0.0-beta.2",
    "@testing-library/jest-dom": "^5.16.4",
    "@testing-library/react": "^13.3.0",
    "@testing-library/user-event": "^13.5.0",
    "@types/jest": "^27.5.2",
    "@types/luxon": "^3.0.0",
    "@types/node": "^16.11.46",
    "@types/react": "^18.0.15",
    "@types/react-dom": "^18.0.6",
    "date-fns": "^2.29.1",
    "luxon": "^3.0.1",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-scripts": "5.0.1",
    "typescript": "^4.7.4",
    "web-vitals": "^2.1.4"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}



Solution

  • At first glance, the problem appears to be your adapter. You claim to be using Luxon. However, your <LocalizationProvider> dateAdapter property is set to use the date-fns adapter.

    Replace the date-fns adapter with the Luxon adapter:

    import { AdapterLuxon } from '@mui/x-date-pickers/AdapterLuxon';
    
    <LocalizationProvider dateAdapter={ AdapterLuxon }>
    

    If you are using the date-fns library elsewhere in your code, you may need to revise that code.