stackworx / formik-mui

Bindings for using Formik with Material-UI

Home Page:https://stackworx.github.io/formik-mui

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Support for Mui X v6

dylmye opened this issue ยท comments

Summary ๐Ÿ’ก

Mui released v6 on the 3rd of March. There are a number of breaking changes but also improvements.

A migration guide is available here: https://mui.com/x/migration/migration-pickers-v5

Motivation ๐Ÿ”ฆ

  • This library should aim to support the latest version of all of the libraries it wraps
  • I had a bug ( mui/mui-x#6948 ) that is resolved by upgrading to v6 and would love to continue using this library
  • I attempted to use this library (DateTimePicker) with mui-x v6 and got some warnings and errors:
The `renderInput` prop has been removed in version 6.0 of the Date and Time Pickers.
You can replace it with the `textField` component slot in most cases.
For more information, please have a look at the migration guide
Uncaught TypeError: date.isBefore is not a function

(the second error is mui/mui-x#8351 )

Thanks!

Looking at this in the next few days

any updates on this?

The components were re-written from the ground up. Spent an hour or two on this but didn't make much progress.
Will probably try again in a week or so

import * as React from 'react';

import TextField, { TextFieldProps } from '@mui/material/TextField';
import {
  DatePicker as MuiDatePicker,
  DatePickerProps as MuiDatePickerProps,
} from '@mui/x-date-pickers/DatePicker';
import { FieldProps, getIn } from 'formik';

import { createErrorHandler } from './errorHandler';

export interface FDatePickerProps<TDate>
  extends FieldProps,
    Omit<MuiDatePickerProps<TDate>, 'name' | 'value' | 'error'> {
  textField?: TextFieldProps;
}

export function fieldToDatePicker<TDate>({
  field: { onChange: _onChange, ...field },
  form: { isSubmitting, touched, errors, setFieldValue, setFieldError, setFieldTouched },
  textField: { helperText, onBlur, ...textField } = {},
  disabled,
  label,
  onChange,
  onError,
  ...props
}: FDatePickerProps<TDate>): MuiDatePickerProps<TDate> {
  const fieldError = getIn(errors, field.name);
  const showError = getIn(touched, field.name) && !!fieldError;

  return {
    slotProps: {
      textField: {
        error: showError,
        helperText: showError ? fieldError : helperText,
        label: label,
        onBlur:
          onBlur ??
          function () {
            setFieldTouched(field.name, true, true);
          },
        ...textField,
      },
    },
    disabled: disabled ?? isSubmitting,
    onChange:
      onChange ??
      function (date) {
        // Do not switch this order, otherwise you might cause a race condition
        // See https://github.com/formium/formik/issues/2083#issuecomment-884831583
        setFieldTouched(field.name, true, false);
        setFieldValue(field.name, date, true);
      },
    onError: onError ?? createErrorHandler(fieldError, field.name, setFieldError),
    ...field,
    ...props,
  };
}

export function FDatePicker<TDate>({ ...props }: FDatePickerProps<TDate>) {
  // custom props
  props.textField = {
    ...props.textField,
    size: 'small',
  };

  return <MuiDatePicker format="YYYY-MM-DD" {...fieldToDatePicker(props)} />;
}

FDatePicker.displayName = 'FormikJoyDatePicker';

This is the version I modified for use with Formik.

However, the downside is that props.textField cannot be passed externally.
I'm trying to figure out why not.

How's it going? :)

    onError: onError ?? createErrorHandler(fieldError, field.name, setFieldError),

@sunho-cho thank you for sharing! what did you end up doing in createErrorHandler?

    onError: onError ?? createErrorHandler(fieldError, field.name, setFieldError),

@sunho-cho thank you for sharing! what did you end up doing in createErrorHandler?

export function createErrorHandler(
fieldError: unknown,
fieldName: string,
setFieldError: (field: string, message?: string) => void
) {
return (error?: ReactNode) => {
if (error !== fieldError && error !== '') {
setFieldError(fieldName, error ? String(error) : undefined);
}
};
}

It's part of this project.