Reactメモ
前提
ReactもTypeScriptも初学者のため、基礎勉強のできるサイトや公式DOC、ZennやQiitaなどでインプットしてます。
アウトプットもしないとなあと思いこの度Zennに初投稿した次第です。
アドバイス・間違いの指摘大歓迎です。でも優しくお願いします🙇♀️
公式の例を元にTypeScriptに直してみる
公式のLEARNREACTよりReactインタラクティビティの追加をtypescriptで記述した版
型定義に悩んだのでメモ。
// 型定義
type ButtonProps = {
onClick: (event: React.MouseEvent<HTMLElement, MouseEvent>) => void;
children: string;
};
// ボタンコンポーネント
const Button = ({ onClick, children }: ButtonProps) => {
return <button onClick={onClick}>{children}</button>;
};
// 型定義
type ToolbarProps = {
onButton1: () => void;
onButton2: () => void;
};
// ツールバーコンポーネント
const Toolbar = ({ onButton1, onButton2 }: ToolbarProps) => {
return (
<>
<Button onClick={onButton1}>ぼたん1</Button>
<Button onClick={onButton2}>ぼたん2</Button>
</>
);
};
// Appコンポーネント
export default function App() {
return (
<Toolbar
onButton1={() => alert("ぼたん1")}
onButton2={() => alert("ぼたん2")}
/>
);
}
型定義の名前の付け方もこれでいいのかわかりません…😂
AIにあってるか聞いた結果
あってるか不安でChatGPTに聞いてみました。
AIが正しいとは限らないので全部鵜呑みにして信じてしまうのはアレですが、参考にと思い。
長いので以下アコーディオン内に格納してます。
ChatGPTの返答
このReactコードはTypeScriptで記述されていますが、型定義は正しいです。コード全体の構造と型定義が一致していることを確認します。
-
ButtonProps
型定義:
type ButtonProps = {
onClick: (event: React.MouseEvent<HTMLElement, MouseEvent>) => void;
children: string;
};
ButtonProps
は、onClick
プロパティがReact.MouseEvent
型のイベントを受け取り、何も返さない(void
)コールバック関数であることを示しています。また、children
プロパティは文字列である必要があります。この型定義はボタンコンポーネントのプロパティを正確に記述しています。
-
Button
コンポーネント:
const Button = ({ onClick, children }: ButtonProps) => {
return <button onClick={onClick}>{children}</button>;
};
Button
コンポーネントは、先ほど定義したButtonProps
型の引数を受け取ります。コンポーネント内部でonClick
とchildren
を使用していますので、型定義とコンポーネントの実装が一致しています。
-
ToolbarProps
型定義:
type ToolbarProps = {
onButton1: () => void;
onButton2: () => void;
};
ToolbarProps
は、onButton1
とonButton2
という2つのプロパティが、それぞれ何も受け取らずに何も返さない(void
)コールバック関数であることを示しています。この型定義はツールバーコンポーネントのプロパティを正確に記述しています。
-
Toolbar
コンポーネント:
const Toolbar = ({ onButton1, onButton2 }: ToolbarProps) => {
return (
<>
<Button onClick={onButton1}>ぼたん1</Button>
<Button onClick={onButton2}>ぼたん2</Button>
</>
);
};
Toolbar
コンポーネントは、先ほど定義したToolbarProps
型の引数を受け取ります。このコンポーネント内でonButton1
とonButton2
を使用していますので、型定義とコンポーネントの実装が一致しています。
全体的に見て、型定義とコンポーネントの実装が一致しており、正しく型付けされたReactコードとなっています。型エラーがない限り、問題なく動作するはずです。
参考
onClickの型定義で参考にさせていただきました。ありがとうございます。
追記
アドバイスいただいたので早速。
しょっぱなの型定義部分について。
// 型定義
type ButtonProps = {
onClick: (event: React.MouseEvent<HTMLElement, MouseEvent>) => void;
children: string;
};
これを、こう↓
type ButtonProps = {
onClick: JSX.IntrinsicElements["button"]["onClick"],
children: ReactNode,
};
もしくはこう↓
type ButtonProps = Pick<JSX.IntrinsicElements["button"], "onClick" | "children">
すると、さらに安全になるとのことでした。
JSX.IntrinsicElements
ってなんぞや?ってなったので検索したりAIに聞いたりしました。
とりあえずファイル開いてみたら、IntrinsicElements interface
にbutton
があった。
["button"]
でこのインターフェイスのbutton
を指定しているのかな。
で、この'button'
にはonClick
と'children'が存在しますよ〜〜ってことかな。
ちょっとまだ理解が追いつかないのでまた色々ググってみようと思います。
ちなみにAIの回答↓
ChatGPT
PickはTypeScriptのユーティリティ型の1つで、指定したオブジェクトから特定のプロパティを抽出するために使用されます。
type ButtonProps = Pick<JSX.IntrinsicElements["button"], "onClick" | "children">
は、JSX.IntrinsicElements["button"]
という型(<button>
要素に対応する型)から、onClick
とchildren
という2つのプロパティを抽出して、新しい型ButtonProps
を作成することを意味します。
Discussion
問題はありませんが、
とか
のような書き方をすると、よりミスの心配が減るのでオススメです。 button 要素の Props の型をそのまま引用できるので。
(Required<T> 型を使えば onClick, children を必須にすることもできます。)
早速アドバイス有難うございます!!
Pickは初めてみました。またあとで調べてみようと思います。
そういった定義の仕方があるのか!と勉強になります。
初歩の初歩を歩んでるとこなので、めちゃくちゃ助かります!ありがとうございます!
TS のユーティリティは、覚えればかなりコーディングの助けになるので、ぜひ使いこなしてください!
サバイバルTypeScriptのアドレスまでご親切にありがとうございます!ユーティリティ型、むずかしそ〜〜ってさらっと見て終わってました。もっかい丁寧に見て学習してみます!!!