component-hook-factories

コンポーネントやフックをネストして定義する高階関数 (higher order function) を使っていないか検証します。コンポーネントやフックは、モジュールレベルで定義するべきです。

ルールの詳細

関数内でコンポーネントやフックを定義すると、呼び出しのたびに新しい関数インスタンスが作成されます。React はそれぞれをまったく別のコンポーネントとして扱うため、コンポーネントツリー全体が破棄されて再作成され、すべての state が失われ、パフォーマンスの問題が発生します。

無効な例

このルールに違反するコードの例です。

// ❌ Factory function creating components
function createComponent(defaultValue) {
return function Component() {
// ...
};
}

// ❌ Component defined inside component
function Parent() {
function Child() {
// ...
}

return <Child />;
}

// ❌ Hook factory function
function createCustomHook(endpoint) {
return function useData() {
// ...
};
}

有効な例

このルールに従ったコードの例です。

// ✅ Component defined at module level
function Component({ defaultValue }) {
// ...
}

// ✅ Custom hook at module level
function useData(endpoint) {
// ...
}

トラブルシューティング

コンポーネントの動作を動的に変えたい

以下のように、カスタマイズしたコンポーネントを作るにはファクトリが必要だと思うかもしれません。

// ❌ Wrong: Factory pattern
function makeButton(color) {
return function Button({children}) {
return (
<button style={{backgroundColor: color}}>
{children}
</button>
);
};
}

const RedButton = makeButton('red');
const BlueButton = makeButton('blue');

代わりに、JSX を children として渡してください。

// ✅ Better: Pass JSX as children
function Button({color, children}) {
return (
<button style={{backgroundColor: color}}>
{children}
</button>
);
}

function App() {
return (
<>
<Button color="red">Red</Button>
<Button color="blue">Blue</Button>
</>
);
}