はじめに
個人で作ったプロジェクトのコンポーネント分割を行っていたところ、propsを10個以上定義する必要がありました。
コンポーネント分割したもののpropsが多く、解決方法はないか調べたことをまとめてみました。
問題
コンポーネント分割した際にpropsが多くなる
return (
<>
<Search
getData={getData}
additivesSearch={additivesSearch}
isDetailedFilterOpen={isDetailedFilterOpen}
setIsDetailedFilterOpen={setIsDetailedFilterOpen}
handleSubmit={handleSubmit}
register={register}
setValue={setValue}
resetField={resetField}
onAdditivesSubmit={onAdditivesSubmit}
handleReset={() => handleReset(true)}
/>
</>
);
}
解決方法
1.オブジェクトにまとめ、スプレッド構文{...オブジェクト名}
を使って設定する
const searchProps = {
getData: getData,
additivesSearch: additivesSearch,
isDetailedFilterOpen: isDetailedFilterOpen,
setIsDetailedFilterOpen: setIsDetailedFilterOpen,
handleSubmit: handleSubmit,
register: register,
setValue: setValue,
resetField: resetField,
onAdditivesSubmit: onAdditivesSubmit,
handleReset: () => handleReset(true)
};
// 省略
return (
<>
<Search {...searchProps} />
</>
);
}
MDNより引用
スプレッド (...) 構文を使うと、配列式や文字列などの反復可能オブジェクトを、0 個以上の引数(関数呼び出しの場合)や要素(配列リテラルの場合)を目的の場所に展開することができます。
スプレッド構文で、オブジェクト内のプロパティを一つずつ展開できると理解しました。
2.Custom Hooksを使う
1の方法は<Search {...searchProps} />
で指定することで、すっきりしましたが、propsの指定が多いことには変わりがありません。
App.tsxに定義していたSearchコンポーネント関連するものをuseSearchFormとしてCustomHooks化
しました。
⇒Searchコンポーネント内に定義することと同じかと思いましたが、再利用できるため、カスタムフック化してみました。
import { useForm, type SubmitHandler } from "react-hook-form";
import type { AdditivesSearch } from "../domain/AdditivesSearch";
export const useSearchForm = (
additivesSearch: (formData: AdditivesSearch) => Promise<void>
) => {
const { handleSubmit, register, setValue, resetField } =
useForm<AdditivesSearch>();
const onAdditivesSubmit: SubmitHandler<AdditivesSearch> = (formData) => {
if (formData.have_additives === "0") {
formData.additives = "";
formData.additivesWord = "";
}
additivesSearch(formData);
};
const handleReset = (have_additives_rest: boolean) => {
resetField("sake_name");
if (have_additives_rest) {
setValue("have_additives", "");
}
resetField("additives");
resetField("additivesWord");
resetField("maker");
};
return {
handleSubmit,
register,
setValue,
resetField,
onAdditivesSubmit,
handleReset,
};
};
import { useSearchForm } from "./hooks/useSearchForm.ts";
const searchForm = useSearchForm(additivesSearch);
const searchProps = {
getData,
additivesSearch,
isDetailedFilterOpen,
setIsDetailedFilterOpen,
...searchForm,
handleReset: () => handleReset(true),
};
// 省略
return (
<>
<Search {...searchProps} />
</>
);
}
おわりに
スプレッド構文は配列のコピー、要素の追加で使うものと思っていましたが、オブジェクトでも使用できることがわかりました。
コンポーネントの分割することで、役割分担できて見やすいと思う一方で、分割するのが難しいとも感じました。
参考