先日Next.jsでWebサービスを開発したのですが、日付入力をする項目があったので、react-datepickerでカレンダーを実装しました。
そのサービスは入力値をsessionStorageに保存する仕様で、もれなく入力した日付も保存します。
保存はうまくいったのですが、保存したデータを取得すると、日付が無効な値であると怒られてしまいました。
事象
実現したかったこと
react-datepickerを使ってsessionStorage(またはlocalStorage)に日付を保存し、ページをロードした際に、保存したデータが反映されるようにしたかったのです。
エラー内容
sessionStorageへの保存は問題なくできたのですが、データの取得でこのようなエラーが表示されました。
どうやら有効な時間の値として認識されていないようです。
Unhandled Runtime Error
RangeError: Invalid time value
エラー発生時の対象ソースコード
react-datepickerのstateはDate型で管理する必要があるため、useStateでDate型のstate変数をcreateStateとして宣言しています。
以下はエラーが発生したときのコードです。
const CreateDatePage = () => {
// state変数と関数
const [createDate, setCreateDate] = useState<Date>(new Date());
// Get Data
useEffect(() => {
if (sessionStorage.getItem(RESUME_DATA) !== null) {
const data: ResumeProps = JSON.parse(sessionStorage.getItem(RESUME_DATA) as string);
setCreateDate(date);
}
}, []);
// Save Data
useEffect(() => {
const timer = setTimeout(() => {
if (sessionStorage.getItem(RESUME_DATA) !== null) {
const data: ResumeProps = JSON.parse(sessionStorage.getItem(RESUME_DATA) as string);
data.createDate = createDate;
sessionStorage.setItem(RESUME_DATA, JSON.stringify(data));
}
}, 500);
return () => {
clearTimeout(timer);
};
}, [createDate]);
return (
<Layout title="作成日">
<DatePicker
dateFormat="yyyy/M/d"
locale="ja"
selected={createDate}
onChange={(date: Date) => setCreateDate(date)}
className="block bg-white border border-gray rounded py-2 px-2 focus:outline-none"
/>
</Layout>
);
};
export default CreateDatePage;
解決策
取得した値はstring型で返ってくるため、Date型に変換する必要がある!
sessionStorageでデータの保存(setItem)や取得(getItem)をする際は、データのやり取りを文字列で行います。
データを取得する際は文字列になっているデータをJSON.parse()でJSONデータに変換し、取得した値をstate関数に設定します。
今回の場合、取得した日付データはstring型として返却されるので以下のコードのようにstate関数に値を設定する前にDate型に変換する必要があるのです。
// Get Data
useEffect(() => {
if (sessionStorage.getItem(RESUME_DATA) !== null) {
const data: ResumeProps = JSON.parse(sessionStorage.getItem(RESUME_DATA) as string);
// string型として返ってきた値をDate型に変換し、その値を格納した変数
const date = typeof data.createDate === 'string' ? new Date(data.createDate) : data.createDate;
// 上記の変数を設定する
setCreateDate(date);
}
}, []);
おわりに
sesstionStorageやlocalStorageでデータの保存や取得をする際は、データのやり取りを文字列で行わなければなりません。
このことをきちんと理解していればなんてことないエラーでしたが、随分と時間を費やしてしまいました😅