2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

formでよく使うElementの型定義覚え書き

Last updated at Posted at 2022-06-30

buttoninput の型定義ってどうだっけ?」
作成するたびにググって確認しているので、いい加減覚えないと。
ということでアウトプットを兼ねて書き記しておきます。

//tsのバージョン
typeScript Version 4.6.4

せっかくなので、Reactでコンポーネントを作りながらやっていまきす。
今回のディレクトリ構成はひとまずこんな感じにしました。
後でしっかり読みたい記事はこちら : 私のフロントエンドディレクトリ構成・テスト観点 2022

App.tsx

App.tsxは、コンポーネントを並べるだけです。

import { useRef } from 'react';
import { Button } from './components/common/form/element/Button'
import { Input } from './components/common/form/element/Input'
import { CheckBox } from './components/common/form/element/CheckBox';
import { Select } from './components/common/form/element/Select';
import { TextArea } from './components/common/form/element/TextArea';

export const App = () => {

  const handler = () => {
    console.log("hello")
  }

  const fruits = [
    { id: 1, name: 'りんご' },
    { id: 2, name: 'バナナ' },
    { id: 3, name: 'メロン' },
  ]

  const ref = useRef<HTMLButtonElement>(null!)
  const catchRef = () => {
    console.log(ref.current)
  }

  return (
    
    <div className="App">
      <button onClick={catchRef}>Buttonのref.current</button>
      <Button
        onClick={handler}
        type='reset'
        name='testButton'
        className='resetButton'
        ref={ref}
      >
        <span>次へ</span>
      </Button>

      <br />

      <Input
        onFocus={handler}
        name='testInput'
        className='inputText'
      />

      <br />
      <CheckBox
        name="fruits"
        defaultChecked={false}
        className='checkBox'
      />
      <br />

      <Select
        name="fruits"
        className='checkBox'
        option={fruits}
      />

      <br />
      <TextArea
        onFocus={handler}
        name='testInput'
        className='textArea'
        placeholder='ご要望'
      />

    </div>
  );
}

使う

ComponentPropsを用いて型を指定する時、refを含んでいるかを明確にするため
ComponentPropsWithoutRef , ComponentPropsWithRef を使用します。
結局 React のコンポーネントにはどうやって型をつければ良いのさ - 蛇足部分

Button component

HTMLxxxElement は、HTMLElementの詳細。
Buttonの場合は、 「HTMLElementの中のHTMLButtonElementだよ」 とジェネリクスで書く必要がある。
HTMLElementはこちら

import { ComponentPropsWithoutRef, forwardRef } from "react";

export const Button = forwardRef<
  HTMLButtonElement,
  ComponentPropsWithoutRef<"button">
>(function ButtonElement({ className, ...props }, ref) {
  return (
    // スプレット構文でまるっと渡す
    <button {...props} ref={ref} />
  );
});


Input component

Buttonコンポーネントとほぼ同じように書くことができる。
HTMLInputElement と宣言するように!

import { ComponentPropsWithoutRef, forwardRef } from "react";

export const Input = forwardRef<
  HTMLInputElement,
  ComponentPropsWithoutRef<"input">
>(function InputElement({ className, ...props }, ref) {
  return (
    <input
      type="text"
      {...props}
      ref={ref}
    />
  );
});

TextArea component

Buttonコンポーネントとほぼ同じように書くことができる。
HTMLTextAreaElement と宣言するように!
*今回は使っていませんが、自動的に高さが可変する react-textarea-autosize はおすすめです。

import { ComponentPropsWithoutRef, forwardRef } from "react";

export const Textarea = forwardRef<
  HTMLTextAreaElement,
  ComponentPropsWithoutRef<"textarea">
>(function TextareaElement({ className, ...props }, ref) {
  return (
    <textarea {...props} ref={ref}/>
  );
});

CheckBox component

もうちょっと改良の余地があると思っています。
引き続き調べる。

type Props = {
  name: string
  defaultChecked: boolean
  className: string
}

export const CheckBox = ({ ...props }: Props) => {
  return <input type='checkbox' {...props} />
}

Select component

下記は簡略的な書き方。
こちらは合わせて HTMLSelectElement についてもしっかり覚えておく必要がある。
React コンポーネントで入力フォームを作成する (1) 自力編

import { FC } from 'react';

type SelectType = JSX.IntrinsicElements["select"]

// こちらでもOK
// type Option = {
//   option: {
//     id: number
//     name: string
//   }[]
// }
// type Props = SelectType & Option

type Option = {
  id: number
  name: string
}
type OptionProps = {
  option: Option[]
}

type Props = SelectType & OptionProps

export const Select: FC<Props> = ({ ...props }) => {
  return (
    <select {...props}>
      {props.option.map((data) =>
        <option key={data.id}>
          {data.name}
        </option>
      )}
    </select >
  )
}


formで使用するElementは汎用的にしておきたいですよね。
覚えはじめは苦戦しましたが、1つ1つ理解していけばするすると入ってきました。
まだふわっとしている部分もありますが、これから固めていきますよ!!!!!

2
1
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
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?