よく登録、変更兼用フォーム画面を作成するのでメモしておく
フォームのベース
ScheduleForm.tsx
import './App.css';
import React, { useEffect, useState } from 'react';
import DatePickerComponent from './components/DatePickerComponent';
import { callGetScheduleApi } from './models/ApiClient';
/**
* フォーム入力項目
*/
interface Form {
id: number | null
title: string
place: string
startDate: Date
endDate: Date
memo: string
}
const ScheduleForm = () => {
// urlパラメータにidがある場合は更新画面、そうでない場合は登録画面とする
const updateFlag = document.location.search.startsWith("?id=") ? true : false;
// urlパラメータにid指定がある場合はidに紐づくスケジュールデータを取得しフォームにセットする
useEffect(() => {
if (updateFlag) {
const id = document.location.search.replace("?id=", "");
// 実際はAPIコールしてスケジュールデータを取得
getSchedule(Number(id));
}
}, [])
/**
* スケジュール取得
* @param id
*/
const getSchedule = async(id: number) => {
const result = await callGetScheduleApi(Number(id));
setFormValue({
id: result.id,
title: result.title,
place: result.place,
startDate: new Date(result.startDate),
endDate: new Date(result.endDate),
memo: result.memo
});
console.log(result)
}
/** 入力フォーム初期値 */
const [formValue, setFormValue] = useState<Form>({
id: null,
title: "",
place: "",
startDate: new Date(),
endDate: new Date(),
memo: ""
});
/** 開始日コンポーネント引数 */
const startDateProps = {
date: formValue.startDate,
onChange: (date: Date) => setFormValue({...formValue, startDate: date})
}
/** 終了日コンポーネント引数 */
const endDateProps = {
date: formValue.endDate,
onChange: (date: Date) => setFormValue({...formValue, endDate: date})
}
return (
<div className="container m-4">
<div className="row mb-4">
<div className="col fs-4">
{updateFlag ? "スケジュール変更" : "スケジュール登録"}
</div>
</div>
<div className="row mb-3">
<div className="col-2 font_xxs">
タイトル
</div>
<div className="col-4">
<input className="form-control" type="text" defaultValue={formValue.title}/>
</div>
</div>
<div className="row mb-3">
<div className="col-2 font_xxs">
場所
</div>
<div className="col-4">
<input className="form-control" type="text" defaultValue={formValue.place}/>
</div>
</div>
<div className="row mb-3">
<div className="col-2 font_xxs">
開始〜終了
</div>
<div className="col-2 me-0">
<DatePickerComponent {...startDateProps}/>
</div>
<div className="col-1 mx-0 text-center">
〜
</div>
<div className="col-2 ms-0">
<DatePickerComponent {...endDateProps}/>
</div>
</div>
<div className="row">
<div className="col-2 font_xxs">
メモ
</div>
<div className="col-4">
<textarea defaultValue={formValue.memo}/>
</div>
</div>
</div>
);
}
export default ScheduleForm;
DatePickerコンポーネント
先日作成したコンポーネントを呼び出し元から引数を渡せるよう改修しました
DatePickerComponent.tsx
import React from "react";
import DatePicker from "react-datepicker";
import "react-datepicker/dist/react-datepicker.css"
interface Props {
date: Date
onChange: (date: Date) => void
}
const DatePickerComponent = ({date = new Date(), onChange}: Props) => {
return (
<DatePicker
dateFormat="yyyy/MM/dd HH:mm"
selected={date}
onChange={date =>{
if (date) {
onChange(date);
}
}}/>
)
}
export default DatePickerComponent;
APIクライアント
API呼び出し処理はtsxファイルに書くとゴチャゴチャしがちなので別ファイルに書きます
ApiClient.ts
interface Schedule {
id: number | null
title: string
place: string
startDate: string
endDate: string
memo: string
}
// テストデータ
const testSchedule: Schedule = {
id: 1234,
title: "アドベントカレンダー書く",
place: "どこでも",
startDate: "2022/12/10 19:00:00.000+09:00",
endDate: "2022/12/15 23:00:00.000+09:00",
memo: "メモメモ"
}
/**
* スケジュール取得API呼び出し
* @param id
* @returns スケジュール
*/
export const callGetScheduleApi = async(id: number): Promise<Schedule> => {
return await fetch(`https://sampleapi221206.com/api/schedules/${id}`).then(result => {
return result.status === 200 ? result.json() : testSchedule;
}).catch(() => {
return testSchedule;
});
}