LoginSignup
1
0

TypeScript勉強して学んだこと!

Last updated at Posted at 2024-06-30

はじめに

こんにちは!WEBエンジニア転職を目指しているK.Yです!
TypeScript勉強してわかったことをメモとして残そうと思って今回書きました。
以下、TSに置き換えたコードです。

コード

import React from 'react';
import { Link } from "react-router-dom";
import { FormEvent, useState } from "react";
import "./App.css";

type InquiryType = {
  name: string ;
  email: string;
  message: string;
};

type ErrorsType = {
  name?: string;
  email?: string;
  message?: string;
};

const InquiryPage: React.FC = () => {
  const [inquiryData, setInquiryData] = useState<InquiryType>({
    name: "",
    email: "",
    message: "",
  });
  const [errors, setErrors] = useState<ErrorsType>({});
  const [isSubmitting, setIsSubmitting] = useState<boolean>(false);

  const handleChange = (
    e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>
  ) => {
    const { id, value } = e.target;
    setInquiryData((prevData) => ({ ...prevData, [id]: value }));
  };

  const validate = () => {
    const tempErrors: ErrorsType = {};
    if (!inquiryData.name) tempErrors.name = "お名前は必須です。";
    if (!inquiryData.email) tempErrors.email = "メールアドレスは必須です。";
    if (!inquiryData.message) tempErrors.message = "本文は必須です。";
    setErrors(tempErrors);
    return Object.keys(tempErrors).length === 0;
  };

  const handleSubmit = async (e: FormEvent): Promise<void> => {
    e.preventDefault();
    if (!validate()) return;

    setIsSubmitting(true);

    try {
      const response = await fetch(
        "https://1hmfpsvto6.execute-api.ap-northeast-1.amazonaws.com/dev/contacts",
        {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify(inquiryData),
        }
      );

      if (!response.ok) throw new Error("Network response was not ok");

      alert("送信しました");
      setInquiryData({ name: "", email: "", message: ""});
      setErrors({});
    } catch (error) {
      console.error("Error submitting form:", error);
    } finally {
      setIsSubmitting(false);
    }
  };

  const handleClear = () => {
    setInquiryData({ name: "", email: "", message: "" });
  };
  return (
    <div className="App">
      <header className="header-App">
        <Link to="/" className="link">
          Blog
        </Link>
        <Link to="/inquiry" className="link">
          お問い合わせ
        </Link>
      </header>

      <div className="inquiry">
        <h1>問合わせフォーム</h1>
        <form id="myForm" onSubmit={handleSubmit}>
          <div className="formItem">
            <label>
              <dl>
                <dt>お名前</dt>
                <div className="text">
                  <dd>
                    <input
                      type="text"
                      id="name"
                      maxLength={30 as number}
                      value={inquiryData.name}
                      onChange={handleChange}
                      disabled={isSubmitting}
                    />
                  </dd>
                  {errors.name && <span>{errors.name}</span>}
                </div>
              </dl>
            </label>

            <div className="label">
              <label>
                <dl>
                  <dt>メールアドレス</dt>
                  <div className="text">
                    <dd>
                      <input
                        type="text"
                        id="email"
                        value={inquiryData.email}
                        onChange={handleChange}
                        disabled={isSubmitting}
                      />
                    </dd>
                    {errors.email && <span>{errors.email}</span>}
                  </div>
                </dl>
              </label>
            </div>
            <div className="label">
              <label>
                <dl>
                  <dt>本文</dt>
                  <div className="text">
                    <dd>
                      <textarea
                        id="message"
                        maxLength={500 as number}
                        value={inquiryData.message}
                        onChange={handleChange}
                        disabled={isSubmitting}
                        rows={10 as number}
                      />
                    </dd>
                    {errors.message && <span>{errors.message}</span>}
                  </div>
                </dl>
              </label>
            </div>
          </div>
          <div className="btn">
            <input type="submit" value="送信" disabled={isSubmitting} />
            <input
              type="reset"
              value="クリア"
              onClick={handleClear}
              disabled={isSubmitting}
            />
          </div>
        </form>
      </div>
    </div>
  );
};

export default InquiryPage;

メモ

type InquiryType = {
  name: string ;
  email: string;
  message: string;
};

type ErrorsType = {
  name?: string;
  email?: string;
  message?: string;
};

const InquiryPage: React.FC = () => {
  const [inquiryData, setInquiryData] = useState<InquiryType>({

上記のconst [inquiryData, setInquiryData] = useState<InquiryType>({は、フォームの入力データを管理するためのステートです。

このステートを型エイリアスで設定してみたのですが、以下のエラーが出た。

型 'string' を型 'number' に割り当てることはできません。

なぜなら、JSXにある<input><textarea>内にnumber型があるから....(maxLength="30"maxLength="500"の部分)

<input
type="text"
id="name"
maxLength="30"
value={inquiryData.name}
onChange={handleChange}
disabled={isSubmitting}
/>

<textarea
type="text"
id="message"
maxLength="500"
value={inquiryData.message}
onChange={handleChange}
disabled={isSubmitting}
rows="10"
/>

色々検索して探しても答えは分からず時間だけが過ぎていく....
そして、ふと思ったこと。
直接、型を設定すればいいのでは?
結果、以下の様に記述したら解決しました!

<input
type="text"
id="name"
maxLength={30 as number}
value={inquiryData.name}
onChange={handleChange}
disabled={isSubmitting}
/>

<textarea
type="text"
id="message"
maxLength={500 as number}
value={inquiryData.message}
onChange={handleChange}
disabled={isSubmitting}
rows={10 as number}
/>

おわり

こんな書き方もできるのかと学べたいい機会だった!
参考になれば幸いです!

1
0
0

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