事象
こちらのフォーム画面でいうと変更画面、初期表示時にAPIから取得した値を書く入力項目にセットする時に一部の項目がundefinedになってしまい値がセットされないことがあった
ここがダメだったぽい
再現した条件はこちら
- react-datepickerを利用した独立DatePickerコンポーネント(フォーム画面本体からインポートされる)
- DatePickerコンポーネントは引数にstring日付をもらい、string⇆Date変換をしている
この条件でフォーム画面に初期値をセットしている useEffect
第2引数を空配列にしていたのが悪さしていた様子。。
import React, { useEffect, useState } from "react";
import DatePicker from "react-datepicker";
import "react-datepicker/dist/react-datepicker.css"
interface Props {
date: string
onChange: (date: string) => void
}
const DatePickerComponent = ({date = "", onChange}: Props) => {
const [selectedDate, setSelectedDate] = useState<Date>();
// 不具合の原因
useEffect(() => {
if (date !== "") {
setSelectedDate(stringToDate(date));
}
}, [])
/**
* string日付をDate型に変換する
* @param strDate
* @returns
*/
const stringToDate = (strDate: string) => {
return new Date(strDate);
}
/**
* Date型をstring日付に変換する
* @param date
* @returns
*/
const dateToString = (date: Date) => {
const ymd = `${date.getFullYear()}/${date.getMonth() + 1}/${date.getDay()}`;
const hm = ("0" + date.getHours()).slice(-2) + ":" + ("0" + date.getMinutes()).slice(-2);
return `${ymd} ${hm}:00.000+09:00`;
}
return (
<DatePicker
dateFormat="yyyy/MM/dd HH:mm"
selected={selectedDate}
onChange={date =>{
if (date) {
onChange(dateToString(date));
}
}}/>
)
}
export default DatePickerComponent;
こうしたら直った(旧)
原因の useEffect
第2引数にpropsから渡る変数 date
を紐づけると解決した
// 不具合の原因
useEffect(() => {
if (date !== "") {
setSelectedDate(stringToDate(date));
}
}, [date])
useMemoを使おう
コメントいただいたように selectedDateの値 = dateの値
なのでこういうケースでは useMemo()
の方が効率が良いようです!!
import React, { useMemo } from "react";
import DatePicker from "react-datepicker";
import "react-datepicker/dist/react-datepicker.css"
interface Props {
date: string
onChange: (date: string) => void
}
const DatePickerComponent = ({date = "", onChange}: Props) => {
/**
* string日付をDate型に変換する
* @param strDate
* @returns
*/
const stringToDate = (strDate: string) => {
if (date === "") return;
return new Date(strDate);
}
/**
* Date型をstring日付に変換する
* @param date
* @returns
*/
const dateToString = (date: Date) => {
const ymd = `${date.getFullYear()}/${date.getMonth() + 1}/${date.getDay()}`;
const hm = ("0" + date.getHours()).slice(-2) + ":" + ("0" + date.getMinutes()).slice(-2);
return `${ymd} ${hm}:00.000+09:00`;
}
const selectedDate = useMemo(() => stringToDate(date), [date]);
return (
<DatePicker
dateFormat="yyyy/MM/dd HH:mm"
selected={selectedDate}
onChange={date =>{
if (date) {
onChange(dateToString(date));
}
}}/>
)
}
export default DatePickerComponent;