Skip to content

Commit

Permalink
[pickers] Use usePickerContext() and usePickerActionsContext() in…
Browse files Browse the repository at this point in the history
…stead of passing props to the `shortcuts` and `toolbar` slots (#15948)
  • Loading branch information
flaviendelangle authored Dec 30, 2024
1 parent dac7c3d commit 61346b3
Show file tree
Hide file tree
Showing 59 changed files with 488 additions and 397 deletions.
8 changes: 3 additions & 5 deletions docs/data/date-pickers/shortcuts/ChangeImportance.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,8 @@ import Stack from '@mui/material/Stack';
import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
import { DatePicker } from '@mui/x-date-pickers/DatePicker';
import {
PickersShortcutsItem,
PickerShortcutChangeImportance,
} from '@mui/x-date-pickers/PickersShortcuts';
import { PickersShortcutsItem } from '@mui/x-date-pickers/PickersShortcuts';
import { PickerChangeImportance } from '@mui/x-date-pickers/models';
import ToggleButtonGroup from '@mui/material/ToggleButtonGroup';
import ToggleButton from '@mui/material/ToggleButton';

Expand Down Expand Up @@ -80,7 +78,7 @@ const shortcutsItems: PickersShortcutsItem<Dayjs | null>[] = [

export default function ChangeImportance() {
const [changeImportance, setChangeImportance] =
React.useState<PickerShortcutChangeImportance>('accept');
React.useState<PickerChangeImportance>('accept');

return (
<LocalizationProvider dateAdapter={AdapterDayjs}>
Expand Down
8 changes: 6 additions & 2 deletions docs/data/date-pickers/shortcuts/CustomizedRangeShortcuts.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
import { StaticDateRangePicker } from '@mui/x-date-pickers-pro/StaticDateRangePicker';

import { useIsValidValue, usePickerContext } from '@mui/x-date-pickers/hooks';

const shortcutsItems = [
{
label: 'This Week',
Expand Down Expand Up @@ -51,7 +53,9 @@ const shortcutsItems = [
];

function CustomRangeShortcuts(props) {
const { items, onChange, isValid, changeImportance = 'accept' } = props;
const { items, changeImportance = 'accept' } = props;
const isValid = useIsValidValue();
const { setValue } = usePickerContext();

if (items == null || items.length === 0) {
return null;
Expand All @@ -63,7 +67,7 @@ function CustomRangeShortcuts(props) {
return {
label: item.label,
onClick: () => {
onChange(newValue, changeImportance, item);
setValue(newValue, { changeImportance, shortcut: item });
},
disabled: !isValid(newValue),
};
Expand Down
7 changes: 5 additions & 2 deletions docs/data/date-pickers/shortcuts/CustomizedRangeShortcuts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
PickersShortcutsProps,
} from '@mui/x-date-pickers/PickersShortcuts';
import { DateRange } from '@mui/x-date-pickers-pro/models';
import { useIsValidValue, usePickerContext } from '@mui/x-date-pickers/hooks';

const shortcutsItems: PickersShortcutsItem<DateRange<Dayjs>>[] = [
{
Expand Down Expand Up @@ -56,7 +57,9 @@ const shortcutsItems: PickersShortcutsItem<DateRange<Dayjs>>[] = [
];

function CustomRangeShortcuts(props: PickersShortcutsProps<DateRange<Dayjs>>) {
const { items, onChange, isValid, changeImportance = 'accept' } = props;
const { items, changeImportance = 'accept' } = props;
const isValid = useIsValidValue<DateRange<Dayjs>>();
const { setValue } = usePickerContext<DateRange<Dayjs>>();

if (items == null || items.length === 0) {
return null;
Expand All @@ -68,7 +71,7 @@ function CustomRangeShortcuts(props: PickersShortcutsProps<DateRange<Dayjs>>) {
return {
label: item.label,
onClick: () => {
onChange(newValue, changeImportance, item);
setValue(newValue, { changeImportance, shortcut: item });
},
disabled: !isValid(newValue),
};
Expand Down
133 changes: 125 additions & 8 deletions docs/data/migration/migration-pickers-v7/migration-pickers-v7.md
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,19 @@ This change causes a few breaking changes:
);
```

- The component passed to the `layout` slot no longer receives the `value` prop, instead you can use the `usePickerContext` hook:

```diff
+import { usePickerContext } from '@mui/x-date-pickers/hooks';

// This contains a small behavior change.
// If the picker receives an invalid date,
// the old value equals `null`.
// the new value equals the invalid date received.
-const { value } = props;
+const { value } = usePickerContext();
```

- The component passed to the `layout` slot no longer receives the `disabled` and `readOnly` props, instead you can use the `usePickerContext` hook:

```diff
Expand All @@ -376,7 +389,7 @@ This change causes a few breaking changes:
+const { readOnly } = usePickerContext();
```

- The component passed to the `layout` slot no longer receives an `isRtl` prop. If you need to access this information, you can use the `useRtl` hook from `@mui/system`:
- The component passed to the `layout` slot no longer receives the `isRtl` prop. If you need to access this information, you can use the `useRtl` hook from `@mui/system`:

```diff
+import { useRtl } from '@mui/system/RtlProvider';
Expand All @@ -398,7 +411,7 @@ This change causes a few breaking changes:
+const isLandscape = orientation === 'landscape';
```

- The component passed to the `layout` slot no longer receives a `wrapperVariant` prop, instead you can use the `usePickerContext` hook:
- The component passed to the `layout` slot no longer receives the `wrapperVariant` prop, instead you can use the `usePickerContext` hook:

```diff
+import { usePickerContext } from '@mui/x-date-pickers/hooks';
Expand All @@ -422,7 +435,8 @@ This change causes a few breaking changes:
+const { onViewChange } = usePickerContext();
```

- The component passed to the `layout` slot no longer receives the `onClear`, `onSetToday`, `onAccept`, `onCancel`, `onOpen`, `onClose` and `onDismiss` props, instead you can use the `usePickerActionsContext` or the `usePickerContext` hooks:
- The component passed to the `layout` slot no longer receives the `onClear`, `onSetToday`, `onAccept`, `onCancel`, `onOpen`, `onClose` `onDismiss`, `onChange` and `onSelectShortcut` props.
You can use the `usePickerActionsContext` or the `usePickerContext` hooks instead:

```diff
+import { usePickerActionsContext } from '@mui/x-date-pickers/hooks';
Expand All @@ -446,7 +460,7 @@ This change causes a few breaking changes:
+ setOpen(true);
+}

-props.onClose();
-const { onClose } = props;
+const { setOpen } = usePickerActionsContext();
+const onClose = event => {
+ event.preventDefault();
Expand All @@ -462,6 +476,18 @@ This change causes a few breaking changes:
-const { onDismiss } = props;
+const { acceptValueChanges } = usePickerActionsContext();
+const onDismiss = acceptValueChanges

-const { onChange } = props;
-onChange(dayjs(), 'partial');
-onChange(dayjs(), 'finish');
+const { setValue } = usePickerActionsContext();
+setValue(dayjs(), { changeImportance: 'set' });
+setValue(dayjs(), { changeImportance: 'accept' });

-const { onSelectShortcut } = props;
-onSelectShortcut(dayjs(), 'accept', myShortcut);
+const { setValue } = usePickerActionsContext();
+setValue(dayjs(), { changeImportance: 'accept', shortcut: myShortcut });
```

:::success
Expand All @@ -471,6 +497,19 @@ This change causes a few breaking changes:

### Slot: `toolbar`

- The component passed to the `toolbar` slot no longer receives the `value` prop, instead you can use the `usePickerContext` hook:

```diff
+import { usePickerContext } from '@mui/x-date-pickers/hooks';

// This contains a small behavior change.
// If the picker receives an invalid date,
// the old value would equal `null`.
// the new value would equal the invalid date received.
-const { value } = props;
+const { value } = usePickerContext();
```

- The component passed to the `toolbar` slot no longer receives the `disabled` and `readOnly` props, instead you can use the `usePickerContext` hook:

```diff
Expand All @@ -483,7 +522,17 @@ This change causes a few breaking changes:
+const { readOnly } = usePickerContext();
```

- The component passed to the `toolbar` slot no longer receives a `view`, `views` and `onViewChange` props, instead you can use the `usePickerContext` hook:
- The component passed to the `toolbar` slot no longer receives the `isLandscape` prop, instead you can use the `usePickerContext` hook:

```diff
+import { usePickerContext } from '@mui/x-date-pickers/hooks';

-const { isLandscape } = props;
+const { orientation } = usePickerContext();
+const isLandscape = orientation === 'landscape';
```

- The component passed to the `toolbar` slot no longer receives the `view`, `views` and `onViewChange` props, instead you can use the `usePickerContext` hook:

```diff
+import { usePickerContext } from '@mui/x-date-pickers/hooks';
Expand All @@ -498,9 +547,28 @@ This change causes a few breaking changes:
+const { onViewChange } = usePickerContext();
```

- The component passed to the `toolbar` slot no longer receives the `onChange` prop.
You can use the `usePickerActionsContext` or the `usePickerContext` hooks instead:

```diff
+import { usePickerActionsContext } from '@mui/x-date-pickers/hooks';

-const { onChange } = props;
-onChange(dayjs(), 'partial');
-onChange(dayjs(), 'finish');
+const { setValue } = usePickerActionsContext();
+setValue(dayjs(), { changeImportance: 'set' });
+setValue(dayjs(), { changeImportance: 'accept' });
```

:::success
The `usePickerContext` also contain all the actions returned by `usePickerActionsContext`.
The only difference is that `usePickerActionsContext` only contains variables with stable references that won't cause a re-render of your component.
:::

### Slot: `tabs`

- The component passed to the `tabs` slot no longer receives a `view`, `views` and `onViewChange` props, instead you can use the `usePickerContext` hook:
- The component passed to the `tabs` slot no longer receives the `view`, `views` and `onViewChange` props, instead you can use the `usePickerContext` hook:

```diff
+import { usePickerContext } from '@mui/x-date-pickers/hooks';
Expand All @@ -517,7 +585,8 @@ This change causes a few breaking changes:

### Slot: `actionBar`

- The component passed to the `actionBar` slot no longer receives the `onClear`, `onSetToday`, `onAccept` and `onCancel` props. You can use the `usePickerActionsContext` or the `usePickerContext` hooks instead:
- The component passed to the `actionBar` slot no longer receives the `onClear`, `onSetToday`, `onAccept` and `onCancel` props.
You can use the `usePickerActionsContext` or the `usePickerContext` hooks instead:

```diff
+import { usePickerActionsContext } from '@mui/x-date-pickers/hooks';
Expand All @@ -540,6 +609,44 @@ This change causes a few breaking changes:
The only difference is that `usePickerActionsContext` only contains variables with stable references that won't cause a re-render of your component.
:::

### Slot: `shortcuts`

- The component passed to the `shortcuts` slot no longer receives the `isLandscape` prop, instead you can use the `usePickerContext` hook:

```diff
+import { usePickerContext } from '@mui/x-date-pickers/hooks';

-const { isLandscape } = props;
+const { orientation } = usePickerContext();
+const isLandscape = orientation === 'landscape';
```

- The component passed to the `shortcuts` slot no longer receives the `onChange` prop.
You can use the `usePickerActionsContext` or the `usePickerContext` hooks instead:

```diff
-const { onChange } = props;
-onChange(dayjs(), 'accept', myShortcut);
+const { setValue } = usePickerActionsContext();
+setValue(dayjs(), { changeImportance: 'accept', shortcut: myShortcut });
```

:::success
The `usePickerContext` also contain all the actions returned by `usePickerActionsContext`.
The only difference is that `usePickerActionsContext` only contains variables with stable references that won't cause a re-render of your component.
:::

- The component passed to the `shortcuts` slot no longer receives the `isValid` prop, instead you can use the `useIsValidValue` hook:

```diff
+import { useIsValidValue } from '@mui/x-date-pickers/hooks';

-const { isValid } = props;
-const isTodayValid = isValid(dayjs());
+const isValidValue = useIsValidValue();
+const isTodayValid = isValidValue(dayjs());
```

## Renamed variables and types

The following variables and types have been renamed to have a coherent `Picker` / `Pickers` prefix:
Expand Down Expand Up @@ -586,7 +693,7 @@ The following variables and types have been renamed to have a coherent `Picker`
+import { PickerValueType } from '@mui/x-date-pickers-pro';
```

- `RangeFieldSection`
- `RangeFieldSection`

```diff
-import { RangeFieldSection } from '@mui/x-date-pickers-pro/models';
Expand All @@ -596,6 +703,16 @@ The following variables and types have been renamed to have a coherent `Picker`
+import { FieldRangeSection } from '@mui/x-date-pickers-pro';
```

- `PickerShortcutChangeImportance`

```diff
-import { PickerShortcutChangeImportance } from '@mui/x-date-pickers/PickersShortcuts';
-import { PickerShortcutChangeImportance } from '@mui/x-date-pickers';

+import { PickerChangeImportance } from '@mui/x-date-pickers/models';
+import { PickerChangeImportance } from '@mui/x-date-pickers';
```

## Hooks breaking changes

### `usePickerContext`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -292,8 +292,8 @@ const DateRangeCalendar = React.forwardRef(function DateRangeCalendar(
// This makes sure that `isWithinRange` works with any time in the start and end day.
const valueDayRange = React.useMemo<PickerRangeValue>(
() => [
value[0] == null || !utils.isValid(value[0]) ? value[0] : utils.startOfDay(value[0]),
value[1] == null || !utils.isValid(value[1]) ? value[1] : utils.endOfDay(value[1]),
!utils.isValid(value[0]) ? value[0] : utils.startOfDay(value[0]),
!utils.isValid(value[1]) ? value[1] : utils.endOfDay(value[1]),
],
[value, utils],
);
Expand Down Expand Up @@ -386,7 +386,7 @@ const DateRangeCalendar = React.forwardRef(function DateRangeCalendar(
const prevValue = React.useRef<PickerRangeValue | null>(null);
React.useEffect(() => {
const date = rangePosition === 'start' ? value[0] : value[1];
if (!date || !utils.isValid(date)) {
if (!utils.isValid(date)) {
return;
}

Expand Down
Loading

0 comments on commit 61346b3

Please sign in to comment.