jaredpalmer / formik

Build forms in React, without the tears 😭
https://formik.org
Apache License 2.0
34k stars 2.79k forks source link

mui datepicker failure TypeError Cannot read properties of undefined (reading 'type') #3493

Open nicoclau opened 2 years ago

nicoclau commented 2 years ago

Bug report

Current Behavior

image

When we select a data we get the error please see the codesandbox below

Expected behavior

we must be able to select a date

Reproducible example

See

https://codesandbox.io/s/formik-codesandbox-template-forked-xonzi?file=/index.js

Your environment

"@emotion/react": "^11.7.1", "@emotion/styled": "^11.6.0", "@material-ui/core": "^4.12.3", "@material-ui/lab": "^4.0.0-alpha.60", "@mui/lab": "^5.0.0-alpha.68", "@mui/material": "^5.4.1", "@mui/x-data-grid": "^5.5.0", "axios": "^0.25.0", "bootstrap": "^4.6.1", "date-fns": "^2.28.0", "formik": "^2.2.9", "jquery": "^3.6.0", "material-ui-search-bar": "^1.0.0", "merge": "^2.1.1", "oidc-client": "^1.11.5", "react": "^16.0.0", "react-bootstrap": "^2.1.2", "react-dom": "^16.0.0", "react-loader-spinner": "^5.1.0", "react-redux": "^7.2.6", "react-router-bootstrap": "^0.25.0", "react-router-dom": "^5.1.2", "react-sortable-tree": "^2.8.0", "reactstrap": "^8.4.1", "redux-logger": "^3.0.6", "redux-thunk": "^2.4.1", "rimraf": "^2.6.2", "semantic-ui-css": "^2.4.1", "semantic-ui-react": "^2.1.1", "uuid": "^8.3.2"

nicoclau commented 2 years ago

i resolved the problem, ok i share it , it can be useful.

To remind the full context

My code didn't work first because

the DateTime picker doesn't set the same type of data as in the initialValues. DateTime picker sends an object containing a property which is the date time in full string format.

in the onChange, we can use the formik object to trigger the SetFieldValue so we can correct the value sent to formik Date.parse will be used so we can send to formik the same data type as in the initial value : number of milliseconds elapsed since January 1, 1970 00:00:00 UTC like the Date.now() used to initialise the departureDate

Date.parse(value) is the number of ms of the date selected, Date.now() is the number of ms of the current date.

const formik = useFormik({
        initialValues: {
            departureTime: Date.now(),
        },
        validate,
        onSubmit: values => {
            alert(JSON.stringify(values, null, 2));
        },
    });

<LocalizationProvider dateAdapter={AdapterDateFns}>
    <DatePicker
        label="Departure Date"
        id="departureDate"
        name="departureDate"
        value={formik.values.departureDate}
        onChange={(value) => {
                formik.setFieldValue('departureDate', Date.parse(value));
                }}
        renderInput={(params) => <TextField {...params} />}
/>
</LocalizationProvider>
martin-trajanovski commented 6 months ago

When I use the DatePicker component with Formik I managed to fix this in the following way:

const FormikUIDatePicker = ({
  name,
  ...otherProps
}: MUIDatePickerProps<PickerValidDate>) => {
const [field, meta, helpers] = useField(name);
const textFieldProps: TextFieldProps = {
    name: name,
    onBlur: () => helpers.setTouched(true, true),
  };

  if (meta && meta.touched && meta.error) {
    textFieldProps.error = true;
    textFieldProps.helperText = meta.error;
  }

  const configDatePicker: MUIDatePickerProps<PickerValidDate> = {
    ...field,
    ...otherProps,
    slotProps: {
      ...otherProps,
      textField: { ...otherProps.slotProps?.textField, ...textFieldProps },
    },
  };

return (
    <DatePicker
      {...configDatePicker}
      onChange={(value) => {
        helpers.setTouched(true, false);
        helpers.setValue(value, true);
      }}
    />
  );
};