3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Reactで<input type="date" />を使う時の無効な日付(2月31日とか)を表示させないやり方

Last updated at Posted at 2020-07-03

はじめに

Reactで<input type="date" />を使って、日付を選択するフォームを作った時に、2月31日とかの無効な日付も選択できてしまうのを防ぎたいと思ったので実装してみました。

inputタグだと味気ないので、material-uiのTextFieldコンポーネントを使ってますが、機能自体は同じです。

日付選択を作る

dateで日付の状態を管理します。
valuedateを受け渡して、onChangeイベントを受け取って状態を更新する普通の処理です。

App.js
export default function App() {
  const [date, setDate] = useState("");

  return (
    <div className="App">
      <FormControl variant="outlined">
        <TextField
          variant="outlined"
          type="date"
          value={date}
          onChange={e => onChangeDate(e}
        />
      </FormControl>
    </div>
  );
}

とりあえずonChangeDate はそのまま状態を更新してみる。

App.js
const onChangeDate = (e) => {
  setDate(e.target.value);
}
```

↑キーとかで選択すると、こんな風に無効な日付が選択できてしまうんですよね・・・
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/619552/4c5d59e3-3610-2067-0c98-2856ccfe1d9b.png)

## onChangeDateでいい感じに調整する

問題点としては

* 2月は閏年があるので、28or29日
* 4/6/9/11月は30日まで

なので、一個前の状態`date`を参照して、書き換えていきます。

無効な日付の時の`e.target.value`には値が入ってないので、値が入っている時はそのまま状態を更新します。

それ以外の場合は月ごとに分岐して書いていきます。

``````js:App.js
const onChangeDate = (e) => {

  if (e.target.value) {
    setDate(e.target.value);
  } else {
    const nowYear = date.slice(0, 4);
    const nowMonth = date.substr(5, 2);
    const nowDate = date.slice(-2);

    if (nowDate !== "01") {
      setDate(`${nowYear}-${nowMonth}-01`);
    }
    else{
      switch (nowMonth) {
        case "02":
          if ((nowYear * 1) % 4 === 0) {
            setDate(`${nowYear}-${nowMonth}-29`);
          } else {
            setDate(`${nowYear}-${nowMonth}-28`);
          }
          break;
        case "04":
        case "06":
        case "09":
        case "11":
          setDate(`${nowYear}-${nowMonth}-30`);
          break;
        default:
          break;
      }
    }
  }
}
```

これで無効な日付がとりあえず入らないようになりました!!

ただこれだと`3/31`から月を2月に変更(↓矢印すると`3/1`に一回なってしまいます

ちょっと気持ち悪いですね。。。

しかし`e.target.value`に値が入ってこないのですし年月日のどの値を変更したかもわからないため
どうしようもなさげです

世に出回っているカレンダーアプリとかの日付は普通に2/31日とか選択できるようになっていて保存できないようにしていたりするのでこれがベストプラクティスなのでしょうかね


## まとめ

今回は日付選択の無効な日付を表示させないようにしてみました

まだ気持ち悪いのでベストプラクティスをご存じの方はコメントをお願いします!!

3
1
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?