React の Functional Component で引数の記載方法を色々試す(TypeScript)
周知
2023/07 にリンクを修正しました、が、2021/06/20 の記事のため、かなり古い情報があります。
いずれ新しい記事書きます。古い情報であることを踏まえて読んでいただければ助かります。
概略
前回の記事[1]で React アプリ(TypeScript 版)の立ち上げをしてみました。
今回は, Create React App によって初期生成されたアプリをアロー関数に書き換えてみたり, Functional Component の記載方法をいろいろ試した内容をまとめています。
(参考)現在の環境の状態
Version 情報 | |
---|---|
React | 17.0.1 |
Node.js | 14.15.4 |
TypeScript | 4.1.3 |
App.tsx をアロー関数に書き換える
Create React App で生成される App.tsx
は Functional Component になっています。(function App()
のあたりです)
React Hooks 登場により, Functional Component でも state 管理などできるようになり, 基本的には Functional Component 使っていくのが主流のようです。(以前は, Class Component が主)
import React from 'react';
function App() {
return (
<div>
{/* 省略 */}
</div>
);
}
export default App;
これをアロー関数で書き換えます。(アロー関数にする諸々のメリットは, this
の取り回しやら簡潔化やらと聞いてますが詳細は他の方の記事をご覧ください)
import React from 'react';
// React.FC は省略可能
// const App = () => {
const App: React.FC = () => {
return (
<div>
{/* 省略 */}
</div>
);
}
export default App;
変わったのは function App
の行あたりです。コメント記載の通り, App 関数の型定義にあたる React.FC
は省略可能です。ただ, 指定してあげる方が明瞭で好みです。
Functional Component の引数指定をいろいろ試す
以降はすべてアロー関数で記載していきます。
前述の App.tsx
は, 引数を受けずに処理を実施しています。では, 引数を受ける Functional Component の書き方とは ... ?と思って調べるといろいろ出てきて困ったのでちょっとだけ試したものをまとめてみます。
引数を受けなくて良い場合のパターン
これは App.tsx
と同じです。値を親から子へ受け渡す必要がない場合は, 以下のように書きます。
順に, React.FC の記載なし版と記載あり版です。
const NoArgsComponent1 = () => {
return (
<div> NoArgsComponent1 </div>
);
}
const NoArgsComponent2: React.FC = () => {
return (
<div> NoArgsComponent2 </div>
);
}
Component の使い方
上記 Functional Component を作成したあとに, Component を差し込みたいところで以下のように記載すれば OK。(例えば App.tsx
)
const App: React.FC = () => {
return (
<div>
<NoArgsComponent1 />
<NoArgsComponent2 />
</div>
);
}
引数を受けて何かしたいパターン
Component にデータを受け渡して表示させるなどの場合, Functional Component の引数を真面目に設定します。
単純なパターン
アロー関数の引数に指定します。(例は arg1, arg2 を設定)
props の型定義として, arg1/arg2 を宣言する形です。
const WithArgsComponent = (props: { arg1: number, arg2: string }) => {
return (
<div>
WithArgsComponent (arg1 = {props.arg1}, arg2 = {props.arg2})
</div>
);
}
React.FC を記載するパターン
上記単純なパターンを, React.FC を用いて記載すると以下になります。(React.FC のジェネリクスに, 引数で受けたいものの型定義を指定します)
const WithArgsComponent: React.FC<{ arg1: number, arg2: string }> = (props) => {
return (
<div>
WithArgsComponent (arg1 = {props.arg1}, arg2 = {props.arg2})
</div>
);
}
props
については, オブジェクトの分割代入に置き換えて以下の書き方でも良いかと思います。
const WithArgsComponent: React.FC<{ arg1: number, arg2: string }> = ({ arg1, arg2 }) => {
return (
<div>
WithArgsComponent (arg1 = {arg1}, arg2 = {arg2})
</div>
);
}
また, ジェネリクスに指定した内容を type
で定義してあげると見通しがよくなります。
type Props = {
arg1: number;
arg2: string;
}
const WithArgsComponent: React.FC<Props> = ({ arg1, arg2 }) => {
return (
<div>
WithArgsComponent (arg1 = {arg1}, arg2 = {arg2})
</div>
);
}
Component の使い方
といろいろ書いたところで, 上記 Component を使用する際には以下のように記載します。(引き続き App.tsx
)
HTML の属性の記載風に, 引数が受け渡しできる感じですね。
const App: React.FC = () => {
const num: number = 1;
const str: string = 'sample';
return (
<div>
<WithArgsComponent arg1={1} arg2='sample' /> {/* 値を直接入れる */}
<WithArgsComponent arg1={num} arg2={str} /> {/* 変数値を入れる */}
</div>
);
}
Child Component を受け渡す場合
Component が Child Component を持つ場合, それらを受け渡すこともできます。
例えば, 以下のように対象の Component(WithArgsComponent
) に Child Component が存在する場合,
const App: React.FC = () => {
return (
<div>
<WithArgsComponent arg1={1} arg2='sample'>
<div> Child ! </div>
</WithArgsComponent>
</div>
);
}
WithArgsComponent
を以下のように記載すれば, Child Component である <div> Child ! </div>
を描画できるようになります。(React.FC を使わない単純な記載です。)
const WithArgsComponent = (props: { arg1: number, arg2: string, children: React.ReactNode }) => {
return (
<div>
WithArgsComponent (arg1 = {props.arg1}, arg2 = {props.arg2})
{props.children}
</div>
);
}
WithArgsComponent
箇所の出力は以下な感じになります。
<div>
WithArgsComponent (arg1 = 1, arg2 = sample)
<div> Child ! </div>
</div>
さて, 単純なパターンで記載しましたが, React.FC で記載すると以下のようになります。
さっきの単純な書き方例の children: React.ReactNode
の記載がなくても分割代入で受け取れています。
type Props = {
arg1: number;
arg2: string;
}
const WithArgsComponent: React.FC<Props> = ({ arg1, arg2, children }) => {
return (
<div>
WithArgsComponent (arg1 = {arg1}, arg2 = {arg2})
{children}
</div>
);
}
この違いは, React.FC
の定義を追いかけてみると, React.FC<P>
-> FunctionComponent<P>
-> PropsWithChildren<P>
にたどり着きます。定義は以下です。
type PropsWithChildren<P> = P & { children?: ReactNode }
React.FC のジェネリクスで指定される P
と, children?: ReactNode
を &
でつないでいます。なので, React.FC<Props>
の記載のみで, children
も受けることができるようになっています。
まとめ
Create React App で作成された App.tsx
内の Functional Component をアロー関数に書き換えつつ, Functional Component の引数の記載方法をいろいろ試してみました。
ちなみに Optional な引数を入れたい場合は { arg: number, optionalArg?: number }
のように ?
を使えば後は同じ感じです。
Discussion