Datepicker is generating TextInput contains an input of type text with both value and defaultValue
- [x] I have searched the Issues to see if this bug has already been reported
- [x] I have tested the latest version
I am initializing the Datepicker to be empty, however, I am getting a warning on the console with: _TextInput contains an input of type text with both value and defaultValue props. Input elements must be either controlled or uncontrolled (specify either the value prop, or the defaultValue prop, but not both).
const [selectedDate, setselectedDate] = useState<Date | null>(null);
<Datepicker className="datepicker-buttons w-full" value={selectedDate} label=""></Datepicker>
Changing the label to =" " make the warning go away
I've got the same issue, is there any possible way to avoid that error occurency?
In my case it's appear only during first render.
Changing the label to =" " didn't help.
Context Nextjs project running locally and testing on Chrome 131.0.6778.109.
@rluders
Yeah, its broken.
Also, onChange does not work for me at all, I cannot get the value out hmm.
Edit: the controlled example in docs is not showing...
https://flowbite-react.com/docs/components/datepicker#controlled-datedatepicker
Does the onChange work for somebody?
It's still broken, I observed a similar behavior... Depending on which options you're using (e.g. value, onChange, defaultValue, label) the behavior is slightly different, but it leads always to unwanted side effects.
Initial Situation
First, sorry for the long text, but that's the detailed analysis. As far as I can tell, I'm happy to disagree, but that's the problem. Basically, the component works even as controlled input, meaning the state can be controlled with value and onChange. However, warnings still occur.
// Test.tsx
import { useState } from "react";
import { Datepicker } from "flowbite-react";
export default function Test() {
const [date, setDate] = useState<Date | null>(null);
return (
<form>
<Datepicker
value={date}
onChange={(newDate) => setDate(newDate)}
placeholder="Select date"
/>
</form>
);
}
In this scenario we have a controlled component (See Controlled Date/Datepicker.) and no date should be selected by default, hence the selected value should be null. At first glance, it seems to work. The internally used text field component is empty and instead the placeholder is shown. But when you select a date using the picker, a warning is thrown.
First Warning
Warning: A component is changing an uncontrolled input to be controlled. This is likely caused by the value changing from undefined to a defined value, which should not happen. Decide between using a controlled or uncontrolled input element for the lifetime of the component. More info: https://reactjs.org/link/controlled-components
The reason for this seems to be that the value for the internal text field is recalculated internally (See Datepicker.tsx:261). If value is null, which is the case, then label is used as value of the internal text field component. But label is undefined, an in consequence the warning is thrown after selecting a date (Switching from undefined to defined). FYI: label seems to be used as some kind of placeholder here, but I don't understand why it doesn't use the placeholder property instead.
// Datepicker.tsx
const displayValue = value === null ? label : getFormattedDate(language, selectedDate || new Date());
...
<TextInput
...
value={displayValue}
/>
Anyways, if you decide to add the label property (e.g. label="Select date") it still seem to work technically and it resolves the former error but it also results in a new one.
Aftereffect
Warning: TextInput contains an input of type text with both value and defaultValue props. Input elements must be either controlled or uncontrolled (specify either the value prop, or the defaultValue prop, but not both). Decide between using a controlled or uncontrolled input element and remove one of these props. More info: https://reactjs.org/link/controlled-components
The reason here is that the component internally calculates the initialDate based on the defaultValue (Not provided, hence undefined). In case of defaultValue is undefined, which is the case, initialDate becomes null (See Datepicker.tsx:129). initialDate is later used to set the internal text field's defaultValue field, which becomes the the label's value in case that initialDate is null (See Datepicker.tsx:296), which is the case. Because we have set label to "Select date", defaultValue is obviously set (!= undefined) at the same time as value is and that leads to the aftereffect.
// Datepicker.tsx
const initialDate = defaultValue ? getFirstDateInRange(defaultValue, minDate, maxDate) : null;
...
<TextInput
...
defaultValue={initialDate ? getFormattedDate(language, initialDate) : label}
/>
PS: I would also be willing to fix the issue myself or rewrite the code once the solution has been discussed.
@MuellerConstantin that's a very thorough breakdown of the issue, thank u!
The next chapter after the #1498 is merged, is to start thinking of really good headless component library we can use, tbh I am really tired of the issues a complex component like Datepicker can have, and yet it wasn't properly discussed nor implemented from the beginning.
So I say and suggest that Datepicker component is a lost cause and shall be entirely replaced by something more robust, such as: React Aria (DatePicker) or Base UI (not yet implemented).
@SutuSebastian Is this a final decision? Because in my opinion it shouldn't be that hard to address this issue, I would address it myself. Of course, I don't know if there are other problems with the component that are more difficult to fix.
@SutuSebastian I reached the same conclusion and went with react-day-picker. It is standalone which makes it perfect for integrating in any UI library. It has fully customizable styles or components.
@SutuSebastian Is this a final decision? Because in my opinion it shouldn't be that hard to address this issue, I would address it myself. Of course, I don't know if there are other problems with the component that are more difficult to fix.
Going headless for really complex components it's for sure, that is why I'm suggesting not to spend a serious amount of time on this, because any fixes brought to this component will only live until the headless approach is implemented.
Feel free to contribute with a fix to this at ur own pace 🚀