I have a website where a user can create an item with a form. This item has a startDate and endDate. I recently had to switch to MUI for functionality purposes and I am struggling to get it to work.
The problem: When a user is done with their item, they save it to their account. They can then go back to this item and choose to edit it. The item data is pre-filled into the form. Here is where the issue is: Anytime I try to import a default value into MUIDatepicker, I receive the error value.isValid is not a function
.
Relevant code:
import { DatePicker as MuiDatePicker } from "@mui/x-date-pickers";
...
const [startDate, setStartDate] = useState(null);
const [endDate, setEndDate] = useState(null);
...
return (
...
<MuiDatePicker
value={startDate}
onChange={(newStartDate) => {
setStartDate(newStartDate);
}}
disablePast
slotProps={{
textField: {
fullWidth: true,
placeholder: "Select a date range",
},
}}
/>
<MuiDatePicker
value={endDate}
onChange={(newEndDate) => {
setEndDate(newEndDate);
}}
disablePast
slotProps={{
textField: {
fullWidth: true,
placeholder: "Select a date range",
},
}}
/>
...
)
When I import the data: I check a couple things. First I check if the data is a string (I know what I'm doing isn't correct, dummy data for testing was created with a string, and previous calendar component also used string for storing values) and then set some values. I'm not all too worried about making the string values work, more so the real data.
if (userItem.startDate !== null) {
if (typeof userItem.startDate === "string") {
setValue("userItem.startDate", moment(userItem.startDate));
setStartDate(moment(userItem.startDate));
} else {
setValue("userItem.startDate", userItem.startDate);
setStartDate(userItem.startDate);
}
}
Issues:
If I import the data as the object that DatePicker
uses: { "$L": "en", "$d": "2025-02-07T05:00:00.000Z", "$y": 2025, "$M": 1, "$D": 7, "$W": 5, "$H": 0, "$m": 0, "$s": 0, "$ms": 0, "$x": {}, "$isDayjsObject": true }
:
I get this error:
So I try something else I've seen, like changing the value to value={moment(startDate)}
.
This causes either an infinite loop of some sort that crashes the app, or it sets the date to the current date and only the current date.
If I try to extract the $d
or even just import a string and convert it to moment, I get the same value.isValid
error.
I tried using dayjs
instead with value={dayjs(startDate)}
but that resulted in a t.clone is not a function
error so no luck there either.
I'm at a bit of a loss here - any solution I think of results in an error. How can I properly handle this sort of data?
EDIT: I noticed that the data for start/endDate is just slightly different than when it is generated:
When using DatePicker:
When importing into DatePicker:
Notice the "M" is not at the start of the object anymore, it is just an object. How could I get the M back? Is that a moment
object?
I have a website where a user can create an item with a form. This item has a startDate and endDate. I recently had to switch to MUI for functionality purposes and I am struggling to get it to work.
The problem: When a user is done with their item, they save it to their account. They can then go back to this item and choose to edit it. The item data is pre-filled into the form. Here is where the issue is: Anytime I try to import a default value into MUIDatepicker, I receive the error value.isValid is not a function
.
Relevant code:
import { DatePicker as MuiDatePicker } from "@mui/x-date-pickers";
...
const [startDate, setStartDate] = useState(null);
const [endDate, setEndDate] = useState(null);
...
return (
...
<MuiDatePicker
value={startDate}
onChange={(newStartDate) => {
setStartDate(newStartDate);
}}
disablePast
slotProps={{
textField: {
fullWidth: true,
placeholder: "Select a date range",
},
}}
/>
<MuiDatePicker
value={endDate}
onChange={(newEndDate) => {
setEndDate(newEndDate);
}}
disablePast
slotProps={{
textField: {
fullWidth: true,
placeholder: "Select a date range",
},
}}
/>
...
)
When I import the data: I check a couple things. First I check if the data is a string (I know what I'm doing isn't correct, dummy data for testing was created with a string, and previous calendar component also used string for storing values) and then set some values. I'm not all too worried about making the string values work, more so the real data.
if (userItem.startDate !== null) {
if (typeof userItem.startDate === "string") {
setValue("userItem.startDate", moment(userItem.startDate));
setStartDate(moment(userItem.startDate));
} else {
setValue("userItem.startDate", userItem.startDate);
setStartDate(userItem.startDate);
}
}
Issues:
If I import the data as the object that DatePicker
uses: { "$L": "en", "$d": "2025-02-07T05:00:00.000Z", "$y": 2025, "$M": 1, "$D": 7, "$W": 5, "$H": 0, "$m": 0, "$s": 0, "$ms": 0, "$x": {}, "$isDayjsObject": true }
:
I get this error:
So I try something else I've seen, like changing the value to value={moment(startDate)}
.
This causes either an infinite loop of some sort that crashes the app, or it sets the date to the current date and only the current date.
If I try to extract the $d
or even just import a string and convert it to moment, I get the same value.isValid
error.
I tried using dayjs
instead with value={dayjs(startDate)}
but that resulted in a t.clone is not a function
error so no luck there either.
I'm at a bit of a loss here - any solution I think of results in an error. How can I properly handle this sort of data?
EDIT: I noticed that the data for start/endDate is just slightly different than when it is generated:
When using DatePicker:
When importing into DatePicker:
Notice the "M" is not at the start of the object anymore, it is just an object. How could I get the M back? Is that a moment
object?
1 Answer
Reset to default 1After more trial and error, I finally figured out a solution:
import dayjs from "dayjs";
...
if (userItem.startDate !== null) {
if (typeof userItem.startDate === "string") {
setValue("userItem.startDate", dayjs(userItem.startDate));
setStartDate(dayjs(userItem.startDate));
} else {
setValue("userItem.startDate", userItem.startDate);
setStartDate(dayjs(userItem.startDate));
}
}
...
<MuiDatePicker
minDate={dayjs(new Date())}
value={startDate && dayjs(startDate)}
onChange={(newStartDate) => {
setStartDate(newStartDate);
}}
disablePast
slotProps={{
textField: {
fullWidth: true,
placeholder: "Select a date range",
},
}}
/>
It seems like dayjs
was the way to go, I was just possibly using it incorrectly at first.