ReactはコンポーネントとHooksを呼び出す

Reactは、ユーザーエクスペリエンスを最適化するために、必要に応じてコンポーネントとHooksをレンダリングします。Reactは宣言型です。コンポーネントのロジックで何をレンダリングするかをReactに指示すると、Reactはユーザーにそれを表示する最適な方法を見つけ出します。


コンポーネント関数を直接呼び出さないでください

コンポーネントはJSXでのみ使用する必要があります。通常の関数として呼び出さないでください。Reactが呼び出す必要があります。

Reactは、レンダリング中にコンポーネント関数をいつ呼び出すかを決定する必要があります。Reactでは、JSXを使用してこれを行います。

function BlogPost() {
return <Layout><Article /></Layout>; // ✅ Good: Only use components in JSX
}
function BlogPost() {
return <Layout>{Article()}</Layout>; // 🔴 Bad: Never call them directly
}

コンポーネントにHooksが含まれている場合、コンポーネントがループ内または条件付きで直接呼び出されると、Hooksのルールに違反しやすくなります。

Reactにレンダリングを調整させることで、多くの利点があります

  • コンポーネントは関数以上のものになります。 Reactは、ツリー内のコンポーネントのアイデンティティに関連付けられたローカル状態などの機能をHooksを通じて拡張できます。
  • コンポーネントタイプは調整に参加します。 Reactにコンポーネントを呼び出させることで、ツリーの概念構造についてもReactに伝えることができます。たとえば、<Feed>のレンダリングから<Profile>ページに移動する場合、Reactはそれらを再利用しようとしません。
  • Reactはユーザーエクスペリエンスを向上させることができます。 たとえば、コンポーネントの呼び出しと呼び出しの間にブラウザにいくつかの作業を実行させることで、大きなコンポーネントツリーの再レンダリングがメインスレッドをブロックしないようにすることができます。
  • より良いデバッグストーリー。 コンポーネントがライブラリが認識しているファーストクラスの市民である場合、開発中にイントロスペクションのための豊富な開発ツールを構築できます。
  • より効率的な調整。 Reactは、ツリー内のどのコンポーネントを再レンダリングする必要があるかを正確に決定し、そうでないコンポーネントをスキップできます。これにより、アプリの速度とスナップショットが向上します。

Hooksを通常の値として渡さないでください

Hooksは、コンポーネントまたはHooks内でのみ呼び出す必要があります。通常の値として渡さないでください。

Hooksを使用すると、React機能でコンポーネントを拡張できます。Hooksは常に関数として呼び出す必要があり、通常の値として渡すことはできません。これにより、*ローカル推論*、つまり開発者がコンポーネントを単独で見てコンポーネントができることをすべて理解する能力が実現します。

このルールに違反すると、Reactはコンポーネントを自動的に最適化しません。

Hookを動的に変更しないでください

Hooksはできるだけ「静的」である必要があります。これは、動的に変更してはならないことを意味します。たとえば、これは高階Hooksを書いてはならないことを意味します

function ChatInput() {
const useDataWithLogging = withLogging(useData); // 🔴 Bad: don't write higher order Hooks
const data = useDataWithLogging();
}

Hooksは不変でなければならず、変更してはなりません。Hookを動的に変更する代わりに、目的の機能を備えたHookの静的バージョンを作成します。

function ChatInput() {
const data = useDataWithLogging(); // ✅ Good: Create a new version of the Hook
}

function useDataWithLogging() {
// ... Create a new version of the Hook and inline the logic here
}

Hookを動的に使用しないでください

また、Hooksを動的に使用しないでください。たとえば、Hookを値として渡すことによってコンポーネントに依存性注入を行う代わりに

function ChatInput() {
return <Button useData={useDataWithLogging} /> // 🔴 Bad: don't pass Hooks as props
}

常にHookの呼び出しをそのコンポーネントにインライン化し、そこでロジックを処理する必要があります。

function ChatInput() {
return <Button />
}

function Button() {
const data = useDataWithLogging(); // ✅ Good: Use the Hook directly
}

function useDataWithLogging() {
// If there's any conditional logic to change the Hook's behavior, it should be inlined into
// the Hook
}

このように、`<Button />` は理解しやすく、デバッグも容易になります。Hookを動的な方法で使用すると、アプリケーションの複雑さが大幅に増加し、局所的な推論が阻害され、長期的にチームの生産性が低下します。また、Hookは条件付きで呼び出されるべきではないというHookのルールを誤って破ってしまう可能性が高くなります。テストのためにコンポーネントをモックする必要がある場合は、モックデータで応答するようにサーバー側をモックする方が良いでしょう。可能であれば、通常はエンドツーエンドテストでアプリケーションをテストする方が効果的です。