LoginSignup
1
0

More than 1 year has passed since last update.

React セット値が画面に反映されない問題

Last updated at Posted at 2022-12-12

事象

こちらのフォーム画面でいうと変更画面、初期表示時にAPIから取得した値を書く入力項目にセットする時に一部の項目がundefinedになってしまい値がセットされないことがあった

開始〜終了がセットされていません。。
スクリーンショット 2022-12-06 21.45.46.png

ここがダメだったぽい

再現した条件はこちら

  1. react-datepickerを利用した独立DatePickerコンポーネント(フォーム画面本体からインポートされる)
  2. 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;
1
0
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
1
0