reactjsmaterial-uireact-final-form

React MUI 5 DatePicker with react-final-form not handling keyboard input


I want to first make clear that this question is about the recently-released MUI 5 DatePicker, i.e. from @mui/x-date-pickers. I previously used the KeyboardDatePicker in the older versions of material-ui with no issues and have taken a similar approach here to integrate the DatePicker with react-final-form.

I have my DatePicker:

function DateInput(props: any) {
  return (
    <LocalizationProvider dateAdapter={AdapterDateFns}>
      <DatePicker
        {...props}
        renderInput={(params: any) => {
          return <TextField {...params} />;
        }}
      />
    </LocalizationProvider>
  );
}

I wrap this in a react-final-form Field:

function DateFormField({
  name,
  label,
  inputFormat
}: {
  name: string;
  label: string;
  inputFormat: string;
}) {
  return (
    <Field name={name} parse={(value) => formatDateTime(value)} type="date">
      {({ input, meta: { touched, invalid, error } }) => (
        <DateInput
          {...input}
          label={label}
          inputFormat={inputFormat}
        />
      )}
    </Field>
  );
}

and I place it into a react-final-form Form:

<Form initialValues={formInitialValues} onSubmit={handleSubmitClick}>
  {({ handleSubmit }) => (
    <form onSubmit={handleSubmit}>
      <DateFormField
        name="asOfDate"
        label="As Of Date"
        inputFormat="MM/dd/yyyy"
      />
      <Button type="submit" variant="contained" color="primary">
        Submit
      </Button>
    </form>
  )}
</Form>

The issue is when trying to type full dates into the DatePicker using the keyboard. My Field receives the correct date, the TextField inside the DatePicker receives the correct date, but the Material UI control itself will display the wrong date. If I set the initial value to something like new Date("0002-07-28"), the DatePicker will display "07/27/2002" (not even 7/28/2002, weirdly enough). This is mainly an issue when you try to type over the year portion of a date (or backspace the in the year portion of the DatePicker to try and retype the year), it tries to push you to the 21st century. If I delete the year portion, I should be able to type e.g. "2021", but on the first keypress of the "2", the DatePicker displays "2002." How can I modify the control to allow input into the year portion of the DatePicker?

I created a working sandbox demonstrating my issue here: https://codesandbox.io/s/mui5-react-final-form-datepicker-9wvtnp?file=/src/Demo.tsx


Solution

  • Not going to be a satisfying answer because I don't know why my approach was wrong, but I got it to work by using the render prop instead of children prop:

    <Field
        name={name}
        validate={getFieldValidator(validators)}
        render={(fieldRenderProps) => (
            <DatePickerInput
                label={label}
                inputFormat={format}
                {...fieldRenderProps}
            />
        )}
    />
    

    and modifying the DateInput object a tiny bit:

    function DateInput(props: any) {
      const {
        input: {
            name, onChange, value
        }
    } = props;
      return (
        <LocalizationProvider dateAdapter={AdapterDateFns}>
          <DatePicker
            name={name}
            onChange={onChange}
            value={(value as any) === '' ? null : value}
            {...props}
            renderInput={(params: any) => {
              return <TextField {...params} />;
            }}
          />
        </LocalizationProvider>
      );
    }
    

    See here for a working CodeSandbox.