MUIのdatePickerで削除ボタンを実装する

# 対象読者
- React、Next.jsを1ヶ月程度触ったことがある
- MUIを使ったアプリを作成している


# MUIって便利ですよね
UI/UXのコンポーネントがまとまっているMUIはとても便利です。
自分でコンポーネントを作る手間が大幅に省けます。
意外とカスタマイズも結構できるので、デザインにも幅を持たせることができます。（センス次第で...)


# datePickerってかゆところに手が届かないんですよね
カレンダー入力はめっちゃありがたいんですけど、入力内容を削除する時が結構めんどくさいんですよね。
1回で全部削除することができないので、YYYY削除して、MM削除して、DD削除してみたいなことしなきゃいけなくて..。
しかも自分は後続で日付フォーマットの変換を入れてたから、一部分を削除するとエラーが出てしまったりして悩んでました。

うーん....
**じゃあdatepickerをカスタマイズしちゃおう！**

# datePickerの基本形の導入方法
基本的な実装は色々な方が行なっているので、そちらを参考にしてください。
自分は[MUIの公式のドキュメント](https://mui.com/x/react-date-pickers/getting-started/)を参考に実装しました。
結局公式ドキュメントが一番頼りになります。
（自分のコードだけを参考にするとライブラリでエラーになると思うので、公式を参考に導入するようにしてください）

# 早速完成形
![スクリーンショット 2023-10-01 23.10.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2009406/714cff8d-f76b-845d-bec2-a8d160c0cf94.png)

やや！なんかXボタンがありますね。
押してみると...
![スクリーンショット 2023-10-01 23.11.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2009406/c32009c1-7dcd-91bf-e21f-f9466e3662b6.png)
入力内容が全て消えました！便利！！


# コード紹介
```tsx
import React, { useState } from "react";
import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs";
import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider";
import { DatePicker } from "@mui/x-date-pickers/DatePicker";
import { IconButton } from "@mui/material";
import ClearIcon from "@mui/icons-material/Clear";
import CalendarTodayIcon from "@mui/icons-material/CalendarToday";

export default function CommonDatePicker(props: any) {
  //カレンダーの表示を制御する
  const [open, setOpen] = useState(false);

  //datePickerの入力値を受け取る
  const [value, setValue] = useState(null);

  //バツボタンを押したらvalueをnullにする
  const onClear = () => {
    setValue(null);
  };

  return (
    <LocalizationProvider dateAdapter={AdapterDayjs}>
      <DatePicker
        format="YYYY/MM/DD"
        sx={{ width: "240px" }}
        open={open}
        onOpen={() => setOpen(true)}
        onClose={() => setOpen(false)}
        value={value}
        onChange={(newValue) => setValue(newValue)}
        slotProps={{
          textField: {
            InputProps: {
              endAdornment: (
                <>
                  {value && (
                    <IconButton onClick={onClear}>
                      <ClearIcon />
                    </IconButton>
                  )}
                  <IconButton onClick={() => setOpen(true)}>
                    <CalendarTodayIcon />
                  </IconButton>
                </>
              ),
            },
          },
        }}
      />
    </LocalizationProvider>
  );
}
```
だいぶ複雑になってしまいましたね。


### このslorPropsがキモです
```tsx
slotProps={{
  textField: {
    InputProps: {
      endAdornment: (
        <>
          {value && (
            <IconButton onClick={onClear}>
              <ClearIcon />
            </IconButton>
          )}
          <IconButton onClick={() => setOpen(true)}>
            <CalendarTodayIcon />
          </IconButton>
        </>
      ),
    },
  },
}}
```
slotPropsとはdatePickerの内部コンポーネントにプロパティを渡すプロパティです。
slotPropsの中で、textFieldのendAdornmentのプロパティを渡すことでバツボタンとカレンダーを表示しています。
（ここの書き方は自分も深く理解していないです）

ここまで辿り着いても問題がありまして、
**バツボタンを導入するためにendAdornmentを指定したらカレンダーが消えてしまうんです...**
カレンダー入力のためのアイコンとバツボタンを2つともendAdornmentで指定する必要があります。
カレンダーの表示/非表示を制御も自分で入れないといけません。
```tsx
open={open}
onOpen={() => setOpen(true)}
onClose={() => setOpen(false)}
```

また、バツボタンは日付が入力されている場合のみ表示したいので、そのような条件も入れています。

```tsx
<>
  {value && (....
....
</>
```
valueはuseStateで管理しています。
```tsx
//datePickerの入力値を受け取る
const [value, setValue] = useState(null);
```


# いかがでしたでしょうか
初めて技術記事を挙げてみました。
色々と調べてここに辿り着いたので、誰かの助けになればと思い書いてみました！
もしこの記事で誰かの時短になればすごく嬉しいです！


間違っている点や、改善できる点などありましたらぜひ教えてください〜！