close
The Wayback Machine - https://web.archive.org/web/20260226024814/https://ja.react.dev/reference/rules/react-calls-components-and-hooks

コンポーネントやフックを呼び出すのは React

ユーザ体験を最適化するために必要に応じてコンポーネントやフックを呼び出すというのは React 自身の責務です。React は宣言型 (declarative) です。あなたは何 (what) をレンダーしたいのかだけを React に伝え、それをどうやって (how) ユーザにうまく表示するのかについては 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
}

コンポーネントにフックが含まれている場合、ループや条件内でコンポーネントを直接呼び出すと、フックのルールにいとも簡単に違反してしまいます。

React にレンダーの指揮権を与えることで、多くの利点が得られます。

  • コンポーネントが単なる関数以上のものになる。ツリー内のコンポーネントの同一性に基づいた処理を行うフックを通じて、React はローカル state などの機能を追加できます。
  • コンポーネントの型情報を差分検出処理時に利用できる。React にコンポーネントの呼び出しを任せることで、ツリーの概念的構造について React はより多くの情報を得られます。たとえば <Feed> から <Profile> ページへとレンダーが移行するとき、React はそれらを再利用しようとせずに済みます。
  • React がユーザ体験を向上させられる。たとえば、大きなコンポーネントツリーの再レンダーがメインスレッドをブロックしないよう、複数のコンポーネントのレンダーの合間にブラウザに一部の作業を行わせることができます。
  • より良いデバッグ体験。ライブラリがコンポーネントのことを基本部品として認識していれば、開発中の調査のためのリッチな開発者ツールを構築できます。
  • より効率的な差分検出処理。React は、ツリー内のどのコンポーネントを再レンダーすべきか正確に把握し、残りをスキップします。これによりアプリの動作は高速でキビキビとしたものになります。

フックを通常の値として取り回さない

フックはコンポーネントまたはフックの内部でのみ呼び出すべきです。通常の値のように取り回してはいけません。

フックは、コンポーネントに React の機能を加えるために使用します。常に関数として呼び出すだけにし、通常の値のように取りまわしてはいけません。これによりローカル・リーズニングが可能に、すなわち開発者がそのコンポーネントだけを見てコンポーネントにできることをすべて理解できるようになります。

このルールを破ると、React はコンポーネントを自動的に最適化することができなくなります。

フックを動的に変更しない

フックは可能な限り「静的」であるべきです。つまり、動的に変更してはいけません。たとえば、高階 (higher-order) フックを書くべきではありません。

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

フックはイミュータブルであるべきで、動的に変更するべきではありません。フックを動的に変更する代わりに、望ましい機能を持つ静的なバージョンのフックを作成してください。

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
}

フックを動的に使用しない

フックを動的に使用してはいけません。例えば以下のように、フックそのものを値としてコンポーネントに渡して依存性注入を行わないようにしてください。

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

代わりにコンポーネント内でインラインでフックをコールし、そこでロジックを処理するべきです。

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 /> を理解しデバッグするのがずっと簡単になります。フックを動的に使用すると、アプリの複雑さが大幅に増し、ローカル・リーズニングを妨げ、長期的にはチームの生産性を低下させます。また、条件付きでフックを呼び出すべきではないというフックのルールを誤って破る可能性も高まります。テストのためにコンポーネントをモックする必要がある場合は、代わりにサーバをモックして固定データで応答する方が良いでしょう。可能であれば、end-to-end テストでアプリをテストする方が通常はより効果的です。