最近、React を使用して開発を行っている際に、見落とされがちな細かい点を発見しましたので、共有します。
関数コンポーネントを使用する際、通常はいくつかの props を定義しますが、引数の渡し方には潜在的な問題があることに注意が必要です。
例#
以下は関数コンポーネントの例です:
const OneSearch = (query, engine) => {
...
}
export default OneSearch;
このコンポーネントを参照する際、以下のように書くことがあります:
<OneSearch query={oneSearchQuery} engine={engine}></OneSearch>
一見すると問題はなさそうですが、関数コンポーネントの定義を注意深く見ると、引数の部分に小さな違いがあることに気づきます:(query, engine)
実際には、以下のようにしたいのです:({ query, engine })
なぜなら、React では、コンポーネントの引数は JavaScript オブジェクトとして渡されるからです。関数コンポーネントを定義する際、引数は (props)
や他の任意の名前、例えば (cop)
と書くことができます。そして、コンポーネントを参照する際、JSX は渡された引数の名前と値を JavaScript オブジェクトとしてパッケージ化し、実引数としてコンポーネントに渡します。props
は単なる慣習的な名前であり、渡された引数にアクセスするために使用することができます。
もう一つの書き方は ({ query, engine })
です。この場合、仮引数はオブジェクトとなり、JavaScript の構文ではこの形式を使用してオブジェクトのプロパティに直接アクセスすることができます。
しかし、(query, engine)
のような書き方を採用すると、状況は異なります。query
は最初の仮引数として、実際には React によってパッケージ化されたオブジェクトを受け取ります。以下のような形式です:
{
query: ...,
engine: ...
}
しかも!このような書き方はエラーを発生させません。なぜなら、JavaScript の関数では、引数の数が足りているかどうか、あるいは多すぎるかどうかに関係なく、エラーを発生させないからです。(少なくとも主要なブラウザの実装ではそうです)
このような逆天的な書き方は、他の言語では早くから問題になっていました。Python では実行時に TypeError が発生し、C/C++ のようなコンパイル言語ではコンパイラが実行前にエラーを発生させます。コンパイルすら通らないのです。
しかし、JavaScript ではこのような振る舞いが許容され、何の警告もなく発生します!引数が多すぎる場合、実引数の順序に従って仮引数に順番に値が渡されます(呼び出し時にどの実引数をどの仮引数に渡すか指定しない場合)。足りない場合も同様です。関数内で引数が指定されていない仮引数を参照しようとすると、その仮引数の値はundefined
になります。ただのundefined
です。警告すらありません。
結論#
したがって、React コンポーネントを定義する際には、(props)
や ({ prop1, prop2 })
の形式を採用することをおすすめします。これにより、潜在的な問題を回避することができます。