diff --git a/content/docs/hooks-effect.md b/content/docs/hooks-effect.md index b40167ec0..97ff78d6c 100644 --- a/content/docs/hooks-effect.md +++ b/content/docs/hooks-effect.md @@ -1,14 +1,14 @@ --- id: hooks-state -title: Using the Effect Hook +title: 副作用フックの利用法 permalink: docs/hooks-effect.html next: hooks-rules.html prev: hooks-intro.html --- -*Hooks* are a new addition in React 16.8. They let you use state and other React features without writing a class. +*フック (hook)* は React 16.8 で追加された新機能です。state などの React の機能を、クラスを書かずに使えるようになります。 -The *Effect Hook* lets you perform side effects in function components: +*副作用 (effect) フック* により、関数コンポーネント内で副作用を実行することができるようになります: ```js{1,6-10} import React, { useState, useEffect } from 'react'; @@ -33,25 +33,25 @@ function Example() { } ``` -This snippet is based on the [counter example from the previous page](/docs/hooks-state.html), but we added a new feature to it: we set the document title to a custom message including the number of clicks. +このスニペットは [1 つ前のページのカウンターの例](/docs/hooks-state.html)に基づいていますが、新しい機能をひとつ加えてあります。クリック回数を含んだカスタムのメッセージをドキュメントのタイトルにセットしているのです。 -Data fetching, setting up a subscription, and manually changing the DOM in React components are all examples of side effects. Whether or not you're used to calling these operations "side effects" (or just "effects"), you've likely performed them in your components before. +データの取得、購読の設定、あるいは React コンポーネント内の DOM の手動での変更、といったものはすべて副作用の例です。これらを "副作用 (side-effect)"(あるいは単に "作用 (effect)")と呼ぶことに慣れているかどうかはともかくとしても、これらのようなことをコンポーネントの中で行ったことはあるでしょう。 ->Tip +> ヒント > ->If you're familiar with React class lifecycle methods, you can think of `useEffect` Hook as `componentDidMount`, `componentDidUpdate`, and `componentWillUnmount` combined. +> React のライフサイクルに馴染みがある場合は、`useEffect` フックを `componentDidMount` と `componentDidUpdate` と `componentWillUnmount` がまとまったものだと考えることができます。 -There are two common kinds of side effects in React components: those that don't require cleanup, and those that do. Let's look at this distinction in more detail. +React コンポーネントにおける副作用には 2 種類あります。クリーンアップコードを必要としない副作用と、必要とする副作用です。これらの違いについて詳しく見ていきましょう。 -## Effects Without Cleanup +## クリーンアップを必要としない副作用 -Sometimes, we want to **run some additional code after React has updated the DOM.** Network requests, manual DOM mutations, and logging are common examples of effects that don't require a cleanup. We say that because we can run them and immediately forget about them. Let's compare how classes and Hooks let us express such side effects. +時に、**React が DOM を更新した後で追加のコードを実行したい**という場合があります。ネットワークリクエストの送信、手動での DOM 改変、ログの記録、といったものがクリーンアップを必要としない副作用の例です。なぜかというとそれらのコードが実行されたあとすぐにそのことを忘れても構わないからです。クラスとフックとでそのような副作用をどのように表現するのか比較してみましょう。 -### Example Using Classes +### クラスを使った例 -In React class components, the `render` method itself shouldn't cause side effects. It would be too early -- we typically want to perform our effects *after* React has updated the DOM. +React のクラスコンポーネントでは、`render` メソッド自体が副作用を起こすべきではありません。そこで副作用を起こすのは早すぎます -- 典型的には、副作用は React が DOM を更新した*あと*に起こすようにしたいのです。 -This is why in React classes, we put side effects into `componentDidMount` and `componentDidUpdate`. Coming back to our example, here is a React counter class component that updates the document title right after React makes changes to the DOM: +そのため React のクラスでは、副作用は `componentDidMount` と `componentDidUpdate` に記載します。例に戻ると、以下が React のクラスで実装したカウンターコンポーネントであり、React が DOM に変更を加えた後に、ドキュメントのタイトルを更新しています。 ```js{9-15} class Example extends React.Component { @@ -83,15 +83,15 @@ class Example extends React.Component { } ``` -Note how **we have to duplicate the code between these two lifecycle methods in class.** +ここで**同じコードを 2 回書かなければならなかった**ことに注意してください。 -This is because in many cases we want to perform the same side effect regardless of whether the component just mounted, or if it has been updated. Conceptually, we want it to happen after every render -- but React class components don't have a method like this. We could extract a separate method but we would still have to call it in two places. +これは、コンポーネントがマウント直後なのか更新後なのかに関係なく、大抵の場合は同じ副作用を起こしたいからです。概念的には、毎回のレンダー時に起こってほしいのですが、React のクラスコンポーネントにはそのようなメソッドは存在していません。副作用のコードを別のメソッドに抽出することは可能ですが、2 か所でそのメソッドを呼ばなければいけないことに変わりはありません。 -Now let's see how we can do the same with the `useEffect` Hook. +では、同じことが `useEffect` フックを用いるとどのように記述できるのか見ていきましょう。 -### Example Using Hooks +### フックを使った例 -We've already seen this example at the top of this page, but let's take a closer look at it: +以下の例は既にこのページの最初で見たものですが、改めて詳しく見ていきましょう。 ```js{1,6-8} import React, { useState, useEffect } from 'react'; @@ -114,15 +114,15 @@ function Example() { } ``` -**What does `useEffect` do?** By using this Hook, you tell React that your component needs to do something after render. React will remember the function you passed (we'll refer to it as our "effect"), and call it later after performing the DOM updates. In this effect, we set the document title, but we could also perform data fetching or call some other imperative API. +**`useEffect` は何をやっているのか?** このフックを使うことで、レンダー後に何かの処理をしないといけない、ということを React に伝えます。React はあなたが渡した関数を覚えており(これを「副作用(関数)」と呼ぶこととします)、DOM の更新の後にそれを呼び出します。この副作用の場合はドキュメントのタイトルをセットしていますが、データを取得したりその他何らかの命令型の API を呼び出したりすることも可能です。 -**Why is `useEffect` called inside a component?** Placing `useEffect` inside the component lets us access the `count` state variable (or any props) right from the effect. We don't need a special API to read it -- it's already in the function scope. Hooks embrace JavaScript closures and avoid introducing React-specific APIs where JavaScript already provides a solution. +**`useEffect` がコンポーネント内で呼ばれるのはなぜか?** コンポーネント内で `useEffect` を記述することで、副作用内から state である `count`(や任意の props)にアクセスできるようになります。それらは既に関数スコープ内に存在するので、参照するための特別な API は必要ありません。フックは JavaScript のクロージャを活用しており、JavaScript で解決できることに対して React 特有の API を導入することはしません。 -**Does `useEffect` run after every render?** Yes! By default, it runs both after the first render *and* after every update. (We will later talk about [how to customize this](#tip-optimizing-performance-by-skipping-effects).) Instead of thinking in terms of "mounting" and "updating", you might find it easier to think that effects happen "after render". React guarantees the DOM has been updated by the time it runs the effects. +**`useEffect` は毎回のレンダー後に呼ばれるのか?** その通りです! デフォルトでは、副作用関数は初回のレンダー時*および*毎回の更新時に呼び出されます。あとで[カスタマイズする方法](#tip-optimizing-performance-by-skipping-effects)について説明します。「マウント」と「更新」という観点で考えるのではなく、「レンダーの後」に副作用は起こる、というように考える方が簡単かもしれません。React は、副作用が実行される時点では DOM が正しく更新され終わっていることを保証します。 -### Detailed Explanation +### 詳しい説明 -Now that we know more about effects, these lines should make sense: +副作用について学んだので、以下の行の意味はお分かりかと思います。 ```js function Example() { @@ -133,21 +133,21 @@ function Example() { }); ``` -We declare the `count` state variable, and then we tell React we need to use an effect. We pass a function to the `useEffect` Hook. This function we pass *is* our effect. Inside our effect, we set the document title using the `document.title` browser API. We can read the latest `count` inside the effect because it's in the scope of our function. When React renders our component, it will remember the effect we used, and then run our effect after updating the DOM. This happens for every render, including the first one. +ここでは `count` という state 変数を宣言し、次に副作用を使うことを React に伝えています。`useEffect` フックには関数を渡しています。この関数こそが副作用関数です。この副作用関数内で `document.title` というブラウザ API を使ってドキュメントのタイトルを設定しています。副作用関数は関数スコープ内にあるため最新の `count` の値は副作用内から参照可能です。React がコンポーネントをレンダーする際に React はこの副作用を覚えておき、DOM を更新した後に呼び出します。これは初回を含む毎回のレンダー時に発生します。 -Experienced JavaScript developers might notice that the function passed to `useEffect` is going to be different on every render. This is intentional. In fact, this is what lets us read the `count` value from inside the effect without worrying about it getting stale. Every time we re-render, we schedule a _different_ effect, replacing the previous one. In a way, this makes the effects behave more like a part of the render result -- each effect "belongs" to a particular render. We will see more clearly why this is useful [later on this page](#explanation-why-effects-run-on-each-update). +経験のある JavaScript 開発者であれば、`useEffect` に渡される関数は毎回のレンダーごとに異なっているということに気付くかもしれません。これは意図的なものです。むしろ、そのようにすることで、古い値を参照してしまう心配なしに副作用関数内から `count` を読むことができるのです。再レンダーごとに、React は*違う*副作用関数をスケジュールし、前のものを置き換えます。ある意味で、こうすることで副作用はレンダーの結果の一部のようにふるまうようになります -- それぞれの副作用は特定のひとつのレンダーと結びついているのです。これがなぜ便利なのかについては[このページの後半](#explanation-why-effects-run-on-each-update)で明らかになるでしょう。 ->Tip +> ヒント > ->Unlike `componentDidMount` or `componentDidUpdate`, effects scheduled with `useEffect` don't block the browser from updating the screen. This makes your app feel more responsive. The majority of effects don't need to happen synchronously. In the uncommon cases where they do (such as measuring the layout), there is a separate [`useLayoutEffect`](/docs/hooks-reference.html#uselayouteffect) Hook with an API identical to `useEffect`. +> `componentDidMount` や `componentDidUpdate` と異なり、`useEffect` でスケジュールされた副作用はブラウザによる画面更新をブロックしません。このためアプリの反応がより良く感じられます。大部分の副作用は同期的に行われる必要がありません。同期的に行う必要がある稀なケース(レイアウトの測定など)のために、`useEffect` と同一の API を有する [`useLayoutEffect`](/docs/hooks-reference.html#uselayouteffect) という別のフックがあります。 -## Effects with Cleanup +## クリーンアップを有する副作用 -Earlier, we looked at how to express side effects that don't require any cleanup. However, some effects do. For example, **we might want to set up a subscription** to some external data source. In that case, it is important to clean up so that we don't introduce a memory leak! Let's compare how we can do it with classes and with Hooks. +ここまでに、クリーンアップを必要としない副作用の表現のしかたについて見てきました。しかし幾つかの副作用ではそれが必要です。例えば何らかの外部のデータソースへの**購読をセットアップしたい**ことがあります。そのような場合、メモリリークが発生しないようにクリーンアップが必要です! クラスの場合とフックの場合とでクリーンアップをどのように行えるのか比較しましょう。 -### Example Using Classes +### クラスを使った例 -In a React class, you would typically set up a subscription in `componentDidMount`, and clean it up in `componentWillUnmount`. For example, let's say we have a `ChatAPI` module that lets us subscribe to a friend's online status. Here's how we might subscribe and display that status using a class: +React のクラスでは、典型的にはデータの購読を `componentDidMount` で行い、クリーンアップを `componentWillUnmount` で行います。例えば、フレンドのオンライン状態を購読することができる `ChatAPI` というモジュールがあるとしましょう。以下がクラスを使ってその状態を購読し、表示する例です。 ```js{8-26} class FriendStatus extends React.Component { @@ -186,17 +186,17 @@ class FriendStatus extends React.Component { } ``` -Notice how `componentDidMount` and `componentWillUnmount` need to mirror each other. Lifecycle methods force us to split this logic even though conceptually code in both of them is related to the same effect. +ここで、`componentDidMount` と `componentWillUnmount` とがお互いに鏡のように対応していないといけないことに注意してください。ライフサイクルメソッドを使うと、2 つのメソッドに書かれているコードが概念上は同一の副作用に関連しているとしても、それらを分割して書かないといけません。 ->Note +> 補足 > ->Eagle-eyed readers may notice that this example also needs a `componentDidUpdate` method to be fully correct. We'll ignore this for now but will come back to it in a [later section](#explanation-why-effects-run-on-each-update) of this page. +> 目ざとい読者なら、この例が完全に正しいものであるためには `componentDidUpdate` も必要だと気付くかもしれません。今のところは気にしないでおきますが、このページの[後に出てくる節](#explanation-why-effects-run-on-each-update)で改めて説明します。 -### Example Using Hooks +### フックを使った例 -Let's see how we could write this component with Hooks. +このコンポーネントをフックを使ってどのように書けるのか見ていきましょう。 -You might be thinking that we'd need a separate effect to perform the cleanup. But code for adding and removing a subscription is so tightly related that `useEffect` is designed to keep it together. If your effect returns a function, React will run it when it is time to clean up: +クリーンアップ用の別の副作用が必要だとお考えかもしれません。しかし購読を開始するコードと解除するコードとは密に関連しているため、`useEffect` はそれらを一緒に書けるようにデザインされています。あなたの副作用が関数を返した場合、React はクリーンアップのタイミングが来たらそれを実行するのです。 ```js{10-16} import React, { useState, useEffect } from 'react'; @@ -223,17 +223,17 @@ function FriendStatus(props) { } ``` -**Why did we return a function from our effect?** This is the optional cleanup mechanism for effects. Every effect may return a function that cleans up after it. This lets us keep the logic for adding and removing subscriptions close to each other. They're part of the same effect! +**副作用内からなぜ関数を返したのか?** これこそが副作用のクリーンアップのためのオプションの仕組みです。すべての副作用は、それをクリーンアップするための関数を返すことができます。これにより購読を開始するためのロジックと解除するためのロジックを並べて書くことができます。両方とも同じ副作用の一部なのです! -**When exactly does React clean up an effect?** React performs the cleanup when the component unmounts. However, as we learned earlier, effects run for every render and not just once. This is why React *also* cleans up effects from the previous render before running the effects next time. We'll discuss [why this helps avoid bugs](#explanation-why-effects-run-on-each-update) and [how to opt out of this behavior in case it creates performance issues](#tip-optimizing-performance-by-skipping-effects) later below. +**React は具体的には副作用のクリーンアップをいつ発生させるのか?** React はコンポーネントがアンマウントされるときにクリーンアップを実行します。しかし、すでに学んだ通り、副作用は 1 回だけでなく毎回のレンダー時に実行されます。このため React は、ひとつ前のレンダーによる副作用を、次回の副作用を実行する前に*も*クリーンアップします。この後で、これが[なぜバグの回避につながるのか](#explanation-why-effects-run-on-each-update)、そして[これがパフォーマンスの問題を引き起こしている場合にどうのようにしてこの挙動を止めるのか](#tip-optimizing-performance-by-skipping-effects)について説明します。 ->Note +> 補足 > ->We don't have to return a named function from the effect. We called it `cleanup` here to clarify its purpose, but you could return an arrow function or call it something different. +> 副作用から名前付きの関数を返す必要はありません。ここでは目的を明示するために `cleanup` という名前にしましたが、アロー関数を返すことも別の名前を付けることも可能です。 -## Recap +## まとめ -We've learned that `useEffect` lets us express different kinds of side effects after a component renders. Some effects might require cleanup so they return a function: +`useEffect` を用いることでコンポーネントのレンダー後に実行される様々な種類の副作用を表現できることを学びました。いくつかの副作用ではクリーンアップが必要な可能性があり、クリーンアップが必要な副作用は関数を返します: ```js useEffect(() => { @@ -244,7 +244,7 @@ We've learned that `useEffect` lets us express different kinds of side effects a }); ``` -Other effects might not have a cleanup phase, and don't return anything. +クリーンアップフェーズが必要ない副作用もあり、その場合は何も返す必要はありません。 ```js useEffect(() => { @@ -252,21 +252,21 @@ Other effects might not have a cleanup phase, and don't return anything. }); ``` -The Effect Hook unifies both use cases with a single API. +副作用フックは両方のユースケースをひとつの API に統合します。 ------------- -**If you feel like you have a decent grasp on how the Effect Hook works, or if you feel overwhelmed, you can jump to the [next page about Rules of Hooks](/docs/hooks-rules.html) now.** +**副作用フックの動作について十分わかったと感じる場合や、逆にもううんざりだという場合は、ここで[次のページ(フックのルールについて)](/docs/hooks-rules.html)に進んでも構いません。** ------------- -## Tips for Using Effects +## 副作用を使う場合のヒント -We'll continue this page with an in-depth look at some aspects of `useEffect` that experienced React users will likely be curious about. Don't feel obligated to dig into them now. You can always come back to this page to learn more details about the Effect Hook. +このページの残りの部分では、経験のある React 利用者が興味を持つかもしれない `useEffect` の深い概念について説明します。今すぐ読み進める必要があるとは思わないでください。副作用フックについて詳細が知りたくなったらいつでもこのページに戻ってくればいいのです。 -### Tip: Use Multiple Effects to Separate Concerns +### ヒント:関心を分離するために複数の副作用を使う -One of the problems we outlined in the [Motivation](/docs/hooks-intro.html#complex-components-become-hard-to-understand) for Hooks is that class lifecycle methods often contain unrelated logic, but related logic gets broken up into several methods. Here is a component that combines the counter and the friend status indicator logic from the previous examples: +フックを[導入する動機](/docs/hooks-intro.html#complex-components-become-hard-to-understand)のページで述べた問題のひとつは、しばしばそれぞれのライフサイクルメソッドに関連のないロジックが含まれ、一方で関連するロジックが複数のメソッドに分割されてしまう、ということです。以下に示すのは、これまでの例で挙げたカウンタとフレンド状態インジケータとを組み合わせたコンポーネントです。 ```js class FriendStatusWithCounter extends React.Component { @@ -303,9 +303,9 @@ class FriendStatusWithCounter extends React.Component { // ... ``` -Note how the logic that sets `document.title` is split between `componentDidMount` and `componentDidUpdate`. The subscription logic is also spread between `componentDidMount` and `componentWillUnmount`. And `componentDidMount` contains code for both tasks. +ここで、`document.title` を設定するためのロジックが `componentDidMount` と `componentDidUpdate` に分離してしまっていることに注意してください。データ購読のためのロジックもやはり `componentDidMount` と `componentWillUnmount` とに分離しています。そして `componentDidMount` には両方の仕事のためのコードが含まれています。 -So, how can Hooks solve this problem? Just like [you can use the *State* Hook more than once](/docs/hooks-state.html#tip-using-multiple-state-variables), you can also use several effects. This lets us separate unrelated logic into different effects: +ではフックはどのようにこの問題を解決するのでしょうか? [*ステート*フックを複数回呼べる](/docs/hooks-state.html#tip-using-multiple-state-variables)のと同様の方法で、複数の副作用を利用することができます。このため、無関係なロジックは別の副作用に分離することが可能です。 ```js{3,8} function FriendStatusWithCounter(props) { @@ -329,13 +329,13 @@ function FriendStatusWithCounter(props) { } ``` -**Hooks lets us split the code based on what it is doing** rather than a lifecycle method name. React will apply *every* effect used by the component, in the order they were specified. +フックを使うことで、ライフサイクルのメソッド名に基づくのではなく、**実際に何をやっているのかに基づいてコードを分割できます**。React はコンポーネントで利用されている*すべての*副作用を、指定されている順番で適用していきます。 -### Explanation: Why Effects Run on Each Update +### 解説:なぜ副作用は毎回の更新ごとに実行されるのか -If you're used to classes, you might be wondering why the effect cleanup phase happens after every re-render, and not just once during unmounting. Let's look at a practical example to see why this design helps us create components with fewer bugs. +クラスに慣れていれば、なぜクリーンアップフェーズは、アンマウント時の 1 度だけではなく再レンダー時に毎回発生するのか、と不思議に思っているかもしれません。実践的な例で、この設計によりなぜバグの少ないコンポーネントが作れるようになるのか見てみましょう。 -[Earlier on this page](#example-using-classes-1), we introduced an example `FriendStatus` component that displays whether a friend is online or not. Our class reads `friend.id` from `this.props`, subscribes to the friend status after the component mounts, and unsubscribes during unmounting: +[このページの前の部分](#example-using-classes-1)で、フレンドがオンラインかどうかを表示する `FriendStatus` コンポーネントの例を示しました。このクラスでは `this.props` の中にある `friend.id` を参照して、コンポーネントがマウントした後にフレンドのステータスを購読し、アンマウント時には購読を解除します: ```js componentDidMount() { @@ -353,9 +353,9 @@ If you're used to classes, you might be wondering why the effect cleanup phase h } ``` -**But what happens if the `friend` prop changes** while the component is on the screen? Our component would continue displaying the online status of a different friend. This is a bug. We would also cause a memory leak or crash when unmounting since the unsubscribe call would use the wrong friend ID. +ですがコンポーネントが表示されている最中に **`friend` プロパティが変わったらどうなるのでしょう**か? このコンポーネントは間違ったフレンドのオンラインステータスを表示し続けてしまいます。これはバグです。しかも誤ったフレンド ID を使って購読解除を呼び出してしまうため、アンマウント時にメモリリークやクラッシュを引き起こしてしまうでしょう。 -In a class component, we would need to add `componentDidUpdate` to handle this case: +クラスコンポーネントの場合は、このようなケースに対処するために `componentDidUpdate` を加える必要がありました。 ```js{8-19} componentDidMount() { @@ -386,9 +386,9 @@ In a class component, we would need to add `componentDidUpdate` to handle this c } ``` -Forgetting to handle `componentDidUpdate` properly is a common source of bugs in React applications. +適切な `componentDidUpdate` 処理をし忘れることが、React アプリケーションにおけるよくあるバグの原因となっていました。 -Now consider the version of this component that uses Hooks: +ではこのコンポーネントのフックを利用したバージョンを見てみましょう。 ```js function FriendStatus(props) { @@ -401,9 +401,9 @@ function FriendStatus(props) { }); ``` -It doesn't suffer from this bug. (But we also didn't make any changes to it.) +動作は変わっておらず、前述のバグも起こらなくなります。 -There is no special code for handling updates because `useEffect` handles them *by default*. It cleans up the previous effects before applying the next effects. To illustrate this, here is a sequence of subscribe and unsubscribe calls that this component could produce over time: +`useEffect` は*デフォルトで*更新を処理するため、更新のための特別なコードは不要です。新しい副作用を適用する前に、ひとつ前の副作用をクリーンアップします。これを例示するため、このコンポーネントが経時的に発生させる可能性のある購読登録と購読解除のシーケンスを示しします: ```js // Mount with { friend: { id: 100 } } props @@ -421,11 +421,11 @@ ChatAPI.subscribeToFriendStatus(300, handleStatusChange); // Run next effect ChatAPI.unsubscribeFromFriendStatus(300, handleStatusChange); // Clean up last effect ``` -This behavior ensures consistency by default and prevents bugs that are common in class components due to missing update logic. +この挙動によりデフォルトで一貫性を保証することができ、クラスコンポーネントでよく見られた更新ロジック書き忘れによるバグを防止することができます。 -### Tip: Optimizing Performance by Skipping Effects +### ヒント:副作用のスキップによるパフォーマンス改善 -In some cases, cleaning up or applying the effect after every render might create a performance problem. In class components, we can solve this by writing an extra comparison with `prevProps` or `prevState` inside `componentDidUpdate`: +いくつかの場合では、副作用のクリーンアップと適用とをレンダーごとに毎回行うことはパフォーマンスの問題を引き起こす可能性があります。クラスコンポーネントの場合、この問題は `componentDidUpdate` の内部で `prevProps` や `prevState` と比較するコードを加えることで解決できました。 ```js componentDidUpdate(prevProps, prevState) { @@ -435,7 +435,7 @@ componentDidUpdate(prevProps, prevState) { } ``` -This requirement is common enough that it is built into the `useEffect` Hook API. You can tell React to *skip* applying an effect if certain values haven't changed between re-renders. To do so, pass an array as an optional second argument to `useEffect`: +これはよくある要求なので、`useEffect` フックの API にはこの動作が組み込まれています。再レンダー間で特定の値が変わっていない場合には副作用の適用を*スキップ*するよう、React に伝えることができるのです。そのためには、`useEffect` のオプションの第 2 引数として配列を渡してください。 ```js{3} useEffect(() => { @@ -443,11 +443,11 @@ useEffect(() => { }, [count]); // Only re-run the effect if count changes ``` -In the example above, we pass `[count]` as the second argument. What does this mean? If the `count` is `5`, and then our component re-renders with `count` still equal to `5`, React will compare `[5]` from the previous render and `[5]` from the next render. Because all items in the array are the same (`5 === 5`), React would skip the effect. That's our optimization. +上記の例では、第 2 引数として `[count]` を渡しています。どういう意味でしょうか? もし `count` が `5` で、次回のコンポーネントのレンダー時にも `count` がまだ `5` であった場合、React は前回のレンダー時に覚えておいた `[5]` と今回のレンダーの `[5]` とを比較します。配列内のすべての要素が同一 (`5 === 5`) ですので、React は副作用をスキップします。これが最適化です。 -When we render with `count` updated to `6`, React will compare the items in the `[5]` array from the previous render to items in the `[6]` array from the next render. This time, React will re-apply the effect because `5 !== 6`. If there are multiple items in the array, React will re-run the effect even if just one of them is different. +再レンダー時に `count` が `6` に変更されている場合、前回レンダー時に覚えておいた `[5]` と今回のレンダー時の `[6]` という配列とを比較します。今回は `5 !== 6` ですので React は副作用を再適用します。配列内に複数の要素がある場合、React は配列内の要素のうちひとつでも変わっている場合に副作用を再実行します。 -This also works for effects that have a cleanup phase: +クリーンアップフェーズがある副作用でも同様に動作します: ```js{6} useEffect(() => { @@ -458,18 +458,18 @@ useEffect(() => { }, [props.friend.id]); // Only re-subscribe if props.friend.id changes ``` -In the future, the second argument might get added automatically by a build-time transformation. +将来的には、ビルド時の変換で第 2 引数を自動で加えられるようになるかもしれません。 ->Note +> 補足 > ->If you use this optimization, make sure the array includes **any values from the outer scope that change over time and that are used by the effect**. Otherwise, your code will reference stale values from previous renders. We'll also discuss other optimization options in the [Hooks API reference](/docs/hooks-reference.html). +> この最適化を使う場合、**時間の経過とともに変化し副作用によって使用される外部スコープからの値**が配列に含まれていることを確認してください。さもないとあなたのコードは以前のレンダー時の古い値を参照してしまうことになります。その他の最適化のオプションについては [Hooks API リファレンス](/docs/hooks-reference.html)で説明しています。 > ->If you want to run an effect and clean it up only once (on mount and unmount), you can pass an empty array (`[]`) as a second argument. This tells React that your effect doesn't depend on *any* values from props or state, so it never needs to re-run. This isn't handled as a special case -- it follows directly from how the inputs array always works. While passing `[]` is closer to the familiar `componentDidMount` and `componentWillUnmount` mental model, we suggest not making it a habit because it often leads to bugs, [as discussed above](#explanation-why-effects-run-on-each-update). Don't forget that React defers running `useEffect` until after the browser has painted, so doing extra work is less of a problem. +> もしも副作用とそのクリーンアップを 1 度だけ(マウント時とアンマウント時にのみ)走らせたいという場合、空の配列 (`[]`) を第 2 引数として渡すことができます。こうすることで、あなたの副作用は props や state の値の*いずれにも*依存していないため再実行する必要が一切ない、ということを React に伝えることができます。これは特別なケースとして処理されているわけではなく、入力配列を普通に処理すればそうなるというだけの話です。`[]` を渡すことはおなじみの `componentDidMount` と `componentWillUnmount` による概念と似ているように感じるでしょうが、[上記で述べたような](#explanation-why-effects-run-on-each-update)バグの原因となりますので、癖でやってしまうことがないようにしてください。また `useEffect` はブラウザが描画し終えた後まで遅延されますので、追加の作業をしてもそれほど問題にならないということもお忘れなく。 -## Next Steps +## 次のステップ -Congratulations! This was a long page, but hopefully by the end most of your questions about effects were answered. You've learned both the State Hook and the Effect Hook, and there is a *lot* you can do with both of them combined. They cover most of the use cases for classes -- and where they don't, you might find the [additional Hooks](/docs/hooks-reference.html) helpful. +おめでとうございます! 長いページでしたが、最終的に副作用に関するほとんどの疑問が解決していることを望みます。これでステートフックと副作用フックの両方を学んだので、それらを組み合わせてやれることが*たくさん*あります。クラスコンポーネントにおけるほとんどのユースケースがカバーされていますが、足りない部分については[他のフック](/docs/hooks-reference.html)が役立つかもしれません。 -We're also starting to see how Hooks solve problems outlined in [Motivation](/docs/hooks-intro.html#motivation). We've seen how effect cleanup avoids duplication in `componentDidUpdate` and `componentWillUnmount`, brings related code closer together, and helps us avoid bugs. We've also seen how we can separate effects by their purpose, which is something we couldn't do in classes at all. +また、[動機](/docs/hooks-intro.html#motivation)のところで述べた問題をフックがどのように解決するのかについてもわかり始めてきたでしょう。副作用のクリーンアップがどのようにして `componentDidUpdate` と `componentWillUnmount` との間でのコードの重複を防ぎ、関係したコードを並べて書くことができるようにし、バグの少ないコードを記述できるようにするのかを見てきました。また目的別に副作用を分割する方法も学びましたが、これはクラスでは全く不可能なことでした。 -At this point you might be questioning how Hooks work. How can React know which `useState` call corresponds to which state variable between re-renders? How does React "match up" previous and next effects on every update? **On the next page we will learn about the [Rules of Hooks](/docs/hooks-rules.html) -- they're essential to making Hooks work.** +この時点で、一体フックがどのように動作しているのか疑問に感じているかもしれません。`useState` のそれぞれの呼び出しがどの state 変数に対応しているのかを、React はどのようにして知るのでしょうか? 更新のたびに、前回と今回の副作用とを React はどのように対応付けるのでしょうか? **次のページでは[フックのルール](/docs/hooks-rules.html)について学びます -- このルールはフックが動作するために必須のものです。**