Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,23 @@ title: exhaustive-deps

<Intro>

Validates that dependency arrays for React hooks contain all necessary dependencies.
React フックの依存配列に、必要な依存値がすべて含まれているか検証します。

</Intro>

## Rule Details {/*rule-details*/}
## ルールの詳細 {/*rule-details*/}

React hooks like `useEffect`, `useMemo`, and `useCallback` accept dependency arrays. When a value referenced inside these hooks isn't included in the dependency array, React won't re-run the effect or recalculate the value when that dependency changes. This causes stale closures where the hook uses outdated values.
`useEffect`、`useMemo`、`useCallback` などの React フックは、依存配列を受け取ります。これらのフック内で参照する値が依存配列に含まれていないと、その依存値が変わっても React はエフェクトの再実行や値の再計算を行いません。これにより、フックが古くなった値を使い続ける、古いクロージャ (stale closure) の問題が発生します。

## Common Violations {/*common-violations*/}
## よくある違反 {/*common-violations*/}

This error often happens when you try to "trick" React about dependencies to control when an effect runs. Effects should synchronize your component with external systems. The dependency array tells React which values the effect uses, so React knows when to re-synchronize.
このエラーは、エフェクトが実行されるタイミングを制御しようとして、依存値について React を「だまそう」としたときによく起こります。エフェクトは、コンポーネントと外部システムを同期するためのものです。依存配列はエフェクトが使う値を React に伝えることで、いつ再同期すべきか判断できるようにします。

If you find yourself fighting with the linter, you likely need to restructure your code. See [Removing Effect Dependencies](/learn/removing-effect-dependencies) to learn how.
リンタと格闘しているようなら、コードの構造を見直す必要があるでしょう。方法については、[エフェクトから依存値を取り除く](/learn/removing-effect-dependencies)を参照してください。

### Invalid {/*invalid*/}
### 無効な例 {/*invalid*/}

Examples of incorrect code for this rule:
このルールに違反するコードの例です。

```js
// ❌ Missing dependency
Expand All @@ -39,9 +39,9 @@ useMemo(() => {
}, [items]); // Missing 'sortOrder'
```

### Valid {/*valid*/}
### 有効な例 {/*valid*/}

Examples of correct code for this rule:
このルールに従ったコードの例です。

```js
// ✅ All dependencies included
Expand All @@ -55,11 +55,11 @@ useEffect(() => {
}, [userId]);
```

## Troubleshooting {/*troubleshooting*/}
## トラブルシューティング {/*troubleshooting*/}

### Adding a function dependency causes infinite loops {/*function-dependency-loops*/}
### 関数を依存配列に追加すると無限ループが起きる {/*function-dependency-loops*/}

You have an effect, but you're creating a new function on every render:
以下では、エフェクトがありますが、レンダーのたびに新しい関数を作成しています。

```js
// ❌ Causes infinite loop
Expand All @@ -72,7 +72,7 @@ useEffect(() => {
}, [logItems]); // Infinite loop!
```

In most cases, you don't need the effect. Call the function where the action happens instead:
ほとんどの場合、このエフェクトは不要です。代わりに、アクションが起きる場所で関数を呼び出してください。

```js
// ✅ Call it from the event handler
Expand All @@ -88,7 +88,7 @@ items.forEach(item => {
});
```

If you genuinely need the effect (for example, to subscribe to something external), make the dependency stable:
エフェクトが本当に必要な場合(例えば、外部の何かをサブスクライブする場合)は、依存値を安定させてください。

```js
// ✅ useCallback keeps the function reference stable
Expand All @@ -106,9 +106,9 @@ useEffect(() => {
}, [items]);
```

### Running an effect only once {/*effect-on-mount*/}
### エフェクトを 1 回だけ実行する {/*effect-on-mount*/}

You want to run an effect once on mount, but the linter complains about missing dependencies:
マウント時にエフェクトを 1 回だけ実行したいのに、依存値が不足しているとリンタに指摘されています。

```js
// ❌ Missing dependency
Expand All @@ -117,7 +117,7 @@ useEffect(() => {
}, []); // Missing 'userId'
```

Either include the dependency (recommended) or use a ref if you truly need to run once:
依存値を依存配列に含める(推奨)か、本当に 1 回だけ実行する必要があるなら ref を使ってください。

```js
// ✅ Include dependency
Expand All @@ -138,9 +138,9 @@ useEffect(() => {
}, [userId]);
```

## Options {/*options*/}
## オプション {/*options*/}

You can configure custom effect hooks using shared ESLint settings (available in `eslint-plugin-react-hooks` 6.1.1 and later):
ESLint の共有設定を使って、カスタムエフェクトフックを設定できます(`eslint-plugin-react-hooks` 6.1.1 以降で利用可能)。

```js
{
Expand All @@ -152,9 +152,9 @@ You can configure custom effect hooks using shared ESLint settings (available in
}
```

- `additionalEffectHooks`: Regex pattern matching custom hooks that should be checked for exhaustive dependencies. This configuration is shared across all `react-hooks` rules.
- `additionalEffectHooks`: 依存値網羅性チェックの対象となるカスタムフック名にマッチする正規表現パターン。この設定は、すべての `react-hooks` ルールで共有されます。

For backward compatibility, this rule also accepts a rule-level option:
後方互換性のため、このルールはルール単位のオプションも受け付けます。

```js
{
Expand All @@ -166,4 +166,4 @@ For backward compatibility, this rule also accepts a rule-level option:
}
```

- `additionalHooks`: Regex for hooks that should be checked for exhaustive dependencies. **Note:** If this rule-level option is specified, it takes precedence over the shared `settings` configuration.
- `additionalHooks`: 依存値網羅性チェックの対象となるカスタムフック名にマッチする正規表現パターン。**注意**:このルール単位のオプションを指定すると、共有の `settings` 設定よりも優先されます。
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,31 @@ title: rules-of-hooks

<Intro>

Validates that components and hooks follow the [Rules of Hooks](/reference/rules/rules-of-hooks).
コンポーネントとフックが[フックのルール](/reference/rules/rules-of-hooks)に従っているか検証します。

</Intro>

## Rule Details {/*rule-details*/}
## ルールの詳細 {/*rule-details*/}

React relies on the order in which hooks are called to correctly preserve state between renders. Each time your component renders, React expects the exact same hooks to be called in the exact same order. When hooks are called conditionally or in loops, React loses track of which state corresponds to which hook call, leading to bugs like state mismatches and "Rendered fewer/more hooks than expected" errors.
React はレンダー間で state を正しく保持するために、フックが呼び出される順番を用います。コンポーネントがレンダーされるたびに、まったく同じフックがまったく同じ順序で呼び出されることを期待しています。フックを条件付きで呼び出したり、ループ内で呼び出したりすると、どの state がどのフック呼び出しに対応するのか React が分からなくなり、state の不一致や "Rendered fewer/more hooks than expected" といったエラーにつながります。

## Common Violations {/*common-violations*/}
## よくある違反 {/*common-violations*/}

These patterns violate the Rules of Hooks:
以下のパターンは、フックのルールに違反します。

- **Hooks in conditions** (`if`/`else`, ternary, `&&`/`||`)
- **Hooks in loops** (`for`, `while`, `do-while`)
- **Hooks after early returns**
- **Hooks in callbacks/event handlers**
- **Hooks in async functions**
- **Hooks in class methods**
- **Hooks at module level**
- **条件分岐内でのフックの呼び出し**(`if`/`else`、三項演算子、`&&`/`||`)
- **ループ内でのフックの呼び出し** (`for`, `while`, `do-while`)
- **早期リターンの後でのフックの呼び出し**
- **コールバックやイベントハンドラ内でのフックの呼び出し**
- **非同期関数内でのフックの呼び出し**
- **クラスメソッド内でのフックの呼び出し**
- **モジュールレベルでのフックの呼び出し**

<Note>

### `use` hook {/*use-hook*/}
### `use` フック {/*use-hook*/}

The `use` hook is different from other React hooks. You can call it conditionally and in loops:
`use` フックは、他の React フックとは異なります。条件付きで呼び出すことも、ループ内で呼び出すこともできます。

```js
// ✅ `use` can be conditional
Expand All @@ -42,17 +42,17 @@ for (const promise of promises) {
}
```

However, `use` still has restrictions:
- Can't be wrapped in try/catch
- Must be called inside a component or hook
ただし、`use` にも制約はあります。
- try/catch で囲むことはできません
- コンポーネントまたはフック内で呼び出す必要があります

Learn more: [`use` API Reference](/reference/react/use)
詳細は、[`use` の API リファレンス](/reference/react/use)を参照してください。

</Note>

### Invalid {/*invalid*/}
### 無効な例 {/*invalid*/}

Examples of incorrect code for this rule:
このルールに違反するコードの例です。

```js
// ❌ Hook in condition
Expand Down Expand Up @@ -80,9 +80,9 @@ try {
const globalState = useState(0); // Outside component
```

### Valid {/*valid*/}
### 有効な例 {/*valid*/}

Examples of correct code for this rule:
このルールに従ったコードの例です。

```js
function Component({ isSpecial, shouldFetch, fetchPromise }) {
Expand All @@ -104,11 +104,11 @@ function Component({ isSpecial, shouldFetch, fetchPromise }) {
}
```

## Troubleshooting {/*troubleshooting*/}
## トラブルシューティング {/*troubleshooting*/}

### I want to fetch data based on some condition {/*conditional-data-fetching*/}
### 条件に応じてデータをフェッチしたい {/*conditional-data-fetching*/}

You're trying to conditionally call useEffect:
以下では、useEffect を条件付きで呼び出そうとしています。

```js
// ❌ Conditional hook
Expand All @@ -119,7 +119,7 @@ if (isLoggedIn) {
}
```

Call the hook unconditionally, check condition inside:
フックは無条件で呼び出すことにし、条件はその内部で確認してください。

```js
// ✅ Condition inside hook
Expand All @@ -132,15 +132,15 @@ useEffect(() => {

<Note>

There are better ways to fetch data rather than in a useEffect. Consider using TanStack Query, useSWR, or React Router 6.4+ for data fetching. These solutions handle deduplicating requests, caching responses, and avoiding network waterfalls.
データのフェッチには、useEffect 内で行うよりも良い方法があります。TanStack Query、useSWR、React Router 6.4 以降の利用を検討してください。これらは、リクエストの重複排除、レスポンスのキャッシュ、ネットワークウォーターフォールの回避に対応しています。

Learn more: [Fetching Data](/learn/synchronizing-with-effects#fetching-data)
詳細は、[データのフェッチ](/learn/synchronizing-with-effects#fetching-data)を参照してください。

</Note>

### I need different state for different scenarios {/*conditional-state-initialization*/}
### 状況に応じて別の state が欲しい {/*conditional-state-initialization*/}

You're trying to conditionally initialize state:
以下では、state を条件付きで初期化しようとしています。

```js
// ❌ Conditional state
Expand All @@ -151,7 +151,7 @@ if (userType === 'admin') {
}
```

Always call useState, conditionally set the initial value:
useState は常に呼び出すようにし、初期値を条件に応じて設定してください。

```js
// ✅ Conditional initial value
Expand All @@ -160,9 +160,9 @@ const [permissions, setPermissions] = useState(
);
```

## Options {/*options*/}
## オプション {/*options*/}

You can configure custom effect hooks using shared ESLint settings (available in `eslint-plugin-react-hooks` 6.1.1 and later):
ESLint の共有設定を使って、カスタムエフェクトフックを設定できます(`eslint-plugin-react-hooks` 6.1.1 以降で利用可能)。

```js
{
Expand All @@ -174,6 +174,6 @@ You can configure custom effect hooks using shared ESLint settings (available in
}
```

- `additionalEffectHooks`: Regex pattern matching custom hooks that should be treated as effects. This allows `useEffectEvent` and similar event functions to be called from your custom effect hooks.
- `additionalEffectHooks`: エフェクトとして扱うカスタムフックにマッチする正規表現パターン。これにより、カスタムエフェクトフックから `useEffectEvent` や同様のイベント関数を呼び出せるようになります。

This shared configuration is used by both `rules-of-hooks` and `exhaustive-deps` rules, ensuring consistent behavior across all hook-related linting.
この共有設定は、`rules-of-hooks` と `exhaustive-deps` の両方のルールで使われ、フック関連のすべてのリントで一貫した動作が保証されます。
Loading