Material-ui-pickers: Cannot change date on static Calendar component

Created on 12 Jul 2019  路  5Comments  路  Source: mui-org/material-ui-pickers

Thank you for your work on this package 馃槃! Attempting to use the static Calendar component but running into an issue you also seem to be experiencing on your static components demo - you cannot set the selected date!

Environment

| Tech | Version |
| -------------------- | ------- |
| @material-ui/pickers | ^3.1.2 |
| material-ui | ^4.1.3 |
| React | 16.8.6 |
| Browser | Chrome v75.0.3770.100 |
| Peer library |date-fns| |

Steps to reproduce

  1. Go to this URL
  2. Try to change the date on the calendar
  3. It does not work
  4. Hence, does not work in my code either

Expected behavior


For the selected date to change upon clicking a new date.

Actual behavior


Selected date remains as the current date.

Live example


https://material-ui-pickers.dev/guides/static-components

EDIT: I should add, it appears from debugging that the onChange callback isn't being called!

Most helpful comment

Found another more elegant workaround (or maybe that is intended, but since documentation for this API missing, we are guessing) without using explicit onChange prop on Calendar component.
Instead need to either define prop "autoOk: true" or "variant: 'inline'", either work.
Example:

const { pickerProps, wrapperProps, inputProps } = usePickerState(
    { value: startDate, onChange: handleStartChange, autoOk: true },
    {
      getDefaultFormat: () => 'MM/dd/yyyy',
    }
  );

  return (
    <div>
      <Paper style={{ overflow: 'hidden' }}>
        <Calendar
          {...pickerProps}
          renderDay={renderDay}
        />
      </Paper>
    </div>
  );

All 5 comments

For anyone else who encounters this issue, I found a workaround until it is addressed!

You have to replicate the onChange function passed to pickerProps in the Calendar props as well. As follows:

EDIT: onChange callback updated to match the signature as per @chattling's comment below.

const { pickerProps, wrapperProps, inputProps } = usePickerState(
    { value: startDate, onChange: handleStartChange },
    {
      getDefaultFormat: () => 'MM/dd/yyyy',
    }
  );

  return (
    <div>
      <Paper style={{ overflow: 'hidden' }}>
        <Calendar
          {...pickerProps}
          onChange={date => handleStartChange(date)}
          renderDay={renderDay}
        />
      </Paper>
    </div>
  );

Actually workaround also need to be updated. When onChange used as in @MattRCherry reply, it gives following warning in console when handleStartChange is defined as state updater function of useState hook - for example const [startDate, handleStartChange] = useState(new Date()):

Warning: State updates from the useState() and useReducer() Hooks don't support the second callback argument. To execute a side effect after rendering, declare it in the component body with useEffect().

This is because the onChange prop of Calendar component defined as:

onChange: (date: MaterialUiPickersDate, isFinish?: boolean) => void;

In order to remove the Warning the code should be:

const { pickerProps, wrapperProps, inputProps } = usePickerState(
    { value: startDate, onChange: handleStartChange },
    {
      getDefaultFormat: () => 'MM/dd/yyyy',
    }
  );

  return (
    <div>
      <Paper style={{ overflow: 'hidden' }}>
        <Calendar
          {...pickerProps}
          onChange={date => handleStartChange(date)}
          renderDay={renderDay}
        />
      </Paper>
    </div>
  );

@chattling Good catch! I've updated my initial answer to reflect this.

Found another more elegant workaround (or maybe that is intended, but since documentation for this API missing, we are guessing) without using explicit onChange prop on Calendar component.
Instead need to either define prop "autoOk: true" or "variant: 'inline'", either work.
Example:

const { pickerProps, wrapperProps, inputProps } = usePickerState(
    { value: startDate, onChange: handleStartChange, autoOk: true },
    {
      getDefaultFormat: () => 'MM/dd/yyyy',
    }
  );

  return (
    <div>
      <Paper style={{ overflow: 'hidden' }}>
        <Calendar
          {...pickerProps}
          renderDay={renderDay}
        />
      </Paper>
    </div>
  );

I am feeling that we need to create custom wrapper to get rid of all that internal things like getDefaultFormat

Was this page helpful?
0 / 5 - 0 ratings