日付ライブラリにdate-fnsを使用した。React + MUIのDatePicker 実装方法

## 完成イメージ

![スクリーンショット 2024-09-22 091301.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3809793/9e383af8-4a08-e5ba-3967-2f2a0315e727.png)


## 目次
1. ドキュメントを実装
1. 見た目を作成
1. DatePickerを日本語化
1. 「次月」「先月」ボタンで日付を変更できるようにする
1. DatePickerで選択した日付をstateで管理

### 1.ドキュメントを実装
https://mui.com/x/react-date-pickers/getting-started/

###### 修正点
* date-fnsライブラリで必要なものをインストール・インポート（注:date-fnsのv2とv3からでインポートの仕方が違います。）
* 日付ライブラリーアダプターをセットアップ



```ts:MonthlySelector.tsx
import { Box, Button } from "@mui/material";
import React from "react";
import { LocalizationProvider } from "@mui/x-date-pickers";
import { AdapterDateFns } from "@mui/x-date-pickers/AdapterDateFnsV3";
import { DatePicker } from "@mui/x-date-pickers/DatePicker";

const MonthSelector = () => {
  return (
    <LocalizationProvider dateAdapter={AdapterDateFns}>
      <Box>
        <Button>
          先月
        </Button>
        <DatePicker />
        <Button>
          次月
        </Button>
      </Box>
    </LocalizationProvider>
  );
};

export default MonthSelector;

```


### 2.見た目を作成

###### 修正点
* ラベルを追加
* 横並び中央に配置
* ボタンにカラーを指定
* DatePickerとボタンの間に余白を追加


```ts:MonthlySelector.tsx
import { Box, Button } from "@mui/material";
import React from "react";
import { LocalizationProvider } from "@mui/x-date-pickers";
import { AdapterDateFns } from "@mui/x-date-pickers/AdapterDateFnsV3";
import { DatePicker } from "@mui/x-date-pickers/DatePicker";

const MonthSelector = () => {
  return (
    <LocalizationProvider dateAdapter={AdapterDateFns}>
      <Box
        sx={{ display: "flex", justifyContent: "center", alignItems: "center" }}
      >
        <Button color={"error"} variant="contained">
          先月
        </Button>
        <DatePicker label="年月を選択" sx={{ mx: 2, background: "white" }} />
        <Button color={"primary"} variant="contained">
          次月
        </Button>
      </Box>
    </LocalizationProvider>
  );
};

export default MonthSelector;

```

### 3.DatePickerを日本語化

###### 修正点


* 今の段階では英語版なので、日本語とは日付の形式が逆になってしまいます。これを修正していきます。
* 今の段階では日付まで選択できるようになっていますが年と月のみ選択できるようにします。
* ポップアップの表示（注:monthAndYearフォーマットが削除されました。calendarHeaderスロットの新しいformatプロップで置き換えることができます。）
    
```ts:MonthlySelector.tsx
import { Box, Button } from "@mui/material";
import React from "react";
import { LocalizationProvider } from "@mui/x-date-pickers";
import { AdapterDateFns } from "@mui/x-date-pickers/AdapterDateFnsV3";
import { DatePicker } from "@mui/x-date-pickers/DatePicker";
import { ja } from "date-fns/locale";

const MonthSelector = () => {
  return (
    <LocalizationProvider dateAdapter={AdapterDateFns} adapterLocale={ja}>
      <Box
        sx={{ display: "flex", justifyContent: "center", alignItems: "center" }}
      >
        <Button color={"error"} variant="contained">
          先月
        </Button>
        <DatePicker
          label="年月を選択"
          sx={{ mx: 2, background: "white" }}
          views={["year", "month"]}
          format="yyyy/MM"
          slotProps={{
            calendarHeader: { format: "yyyy年 MM月" },
            toolbar: {
              toolbarFormat: "yyyy年 MM月",
            },
          }}
        />
        <Button color={"primary"} variant="contained">
          次月
        </Button>
      </Box>
    </LocalizationProvider>
  );
};

export default MonthSelector;

```

### 4.「次月」「先月」ボタンで日付を変更できるようにする

###### 修正点
* 日付をStateで管理
* DatePickerのvalueにStateの値を設定
* 「次月」「先月」ボタンを押したときの処理を追加


```ts:MonthlySelector.tsx
import { Box, Button } from "@mui/material";
import React from "react";
import { LocalizationProvider } from "@mui/x-date-pickers";
import { AdapterDateFns } from "@mui/x-date-pickers/AdapterDateFnsV3";
import { DatePicker } from "@mui/x-date-pickers/DatePicker";
import { ja } from "date-fns/locale";
import { addMonths } from "date-fns";
import { useState } from "react"
import { addMonths } from "date-fns";




const MonthSelector = () => {

const [currentMonth, setCurrentMonth] = useState(new Date())

  const handlePreviousMonth = () => {
    const previousMonth = addMonths(currentMonth, -1);
    console.log(previousMonth);
    setCurrentMonth(previousMonth);
  };
  const handleNextMonth = () => {
    const nextMonth = addMonths(currentMonth, +1);
    setCurrentMonth(nextMonth);
  };
  return (
    <LocalizationProvider dateAdapter={AdapterDateFns} adapterLocale={ja}>
      <Box
        sx={{ display: "flex", justifyContent: "center", alignItems: "center" }}
      >
        <Button
          onClick={handlePreviousMonth}
          color={"error"}
          variant="contained"
        >
          先月
        </Button>
        <DatePicker
          value={currentMonth}
          label="年月を選択"
          sx={{ mx: 2, background: "white" }}
          views={["year", "month"]}
          format="yyyy/MM"
          slotProps={{
            calendarHeader: { format: "yyyy年 MM月" },
            toolbar: {
              toolbarFormat: "yyyy年 MM月",
            },
          }}
        />
        <Button onClick={handleNextMonth} color={"primary"} variant="contained">
          次月
        </Button>
      </Box>
    </LocalizationProvider>
  );
};

export default MonthSelector;

```

### 5.DatePickerで選択した日付をstateで管理（完成系コード）

###### 修正点
* DatePickerで日付を変更したときの処理を追加
* onChangeでDatePickerで選択した日付をstateで管理

```ts:MonthlySelector.tsx
import { Box, Button } from "@mui/material";
import React from "react";
import { LocalizationProvider } from "@mui/x-date-pickers";
import { AdapterDateFns } from "@mui/x-date-pickers/AdapterDateFnsV3";
import { DatePicker } from "@mui/x-date-pickers/DatePicker";
import { ja } from "date-fns/locale";
import { addMonths } from "date-fns";
import { useState } from "react";

const MonthSelector = () => {
  const [currentMonth, setCurrentMonth] = useState(new Date());

  const handleDateChange = (newDate: Date | null) => {
    if (newDate) {
      setCurrentMonth(newDate);
    }
  };
  const handlePreviousMonth = () => {
    const previousMonth = addMonths(currentMonth, -1);
    console.log(previousMonth);
    setCurrentMonth(previousMonth);
  };
  const handleNextMonth = () => {
    const nextMonth = addMonths(currentMonth, +1);
    setCurrentMonth(nextMonth);
  };
  return (
    <LocalizationProvider dateAdapter={AdapterDateFns} adapterLocale={ja}>
      <Box
        sx={{ display: "flex", justifyContent: "center", alignItems: "center" }}
      >
        <Button
          onClick={handlePreviousMonth}
          color={"error"}
          variant="contained"
        >
          先月
        </Button>
        <DatePicker
          onChange={handleDateChange}
          value={currentMonth}
          label="年月を選択"
          sx={{ mx: 2, background: "white" }}
          views={["year", "month"]}
          format="yyyy/MM"
          slotProps={{
            calendarHeader: { format: "yyyy年 MM月" },
            toolbar: {
              toolbarFormat: "yyyy年 MM月",
            },
          }}
        />
        <Button onClick={handleNextMonth} color={"primary"} variant="contained">
          次月
        </Button>
      </Box>
    </LocalizationProvider>
  );
};

export default MonthSelector;

```

ここまで変更出来れば、完成イメージのようになるかなと思います。
ご覧いただききありがとうございました。