Skip to content
Merged
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 @@ -14282,13 +14282,13 @@ useEffect(() => {
}, [roomId]);
```

多くのユーザはこのコードを「マウント時に `roomId` に接続し、`roomId` が変更されるたびに古いルームから切断して接続を再確立する」のように読んでしまいます。しかしこれでは、コンポーネントのライフサイクルの視点から考えてしまっています。つまり、エフェクトを正しく書くためにコンポーネントライフサイクルの全状態を考える必要があるのです。これは難しいことです。コンポーネントの視点で考えていると、エフェクトがクラスのライフサイクルよりも難しいと感じてしまうのは理解できます
多くのユーザはこのコードを「マウント時に `roomId` に接続し、`roomId` が変更されるたびに古いルームから切断して接続を再確立する」のように解釈してしまいます。しかし、このようにコンポーネントのライフサイクルの視点で考えると、エフェクトを正しく書くにはコンポーネントライフサイクルの全状態を考慮する必要があることになってしまいます。これは難しいことなので、コンポーネント視点だとクラスのライフサイクルよりもエフェクトの方が難しく見えるのは、無理もないことです
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

原文を大きな節単位で分解するとこんな感じ。どの★も事実と異なる思い込み、およびその思い込みから導き出される(誤った)結論なので、

背理法を使った証明の文章のように、その「反現実性」がわかりやすいように、文末表現や接続のしかたを工夫してみました。

  • Many users would read this code as
    • ★ "on mount, connect to the roomId. whenever roomId changes, disconnect to the old room and re-create the connection".
  • However, this is thinking from the component's lifecycle perspective
    • , which means ★ you will need to think of every component lifecycle state to write the Effect correctly.
  • This can be difficult, so it's understandable that Effects seem ★ harder than class lifecycles when using the component perspective.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

あと、末尾の部分では、主語「エフェクトの方が」をあえて末尾に移動して述語「難しく見える」に近づけています。

「トピックを先頭から移動しないことで、トピックをわかりやすくする」のが英語ドキュメントの和訳として自然かもしれませんが、文の構造が複雑でわかりにくいのでそれを軽減するのを優先してこのようにしてみました。


### 依存配列のないエフェクト {/*effects-without-dependencies*/}

代わりに、エフェクトの視点から考える方がベターです。エフェクトはコンポーネントのライフサイクルについて知りません。同期を開始する方法と停止する方法が記述されているだけです。ユーザがこのようにエフェクトを考えることでエフェクトは書きやすくなり、必要次第で何度も開始・停止されることに対して、より頑強になります。

エフェクトをコンポーネントの視点から考えてしまう理由について時間をかけて調査し、その一因が依存配列にあると考えるようになりました。常に目の前にあって書かなければならないもののため、コードが何に「反応」しているのかを意識せざるを得ず、だから「これらの値が変わったらこれを行え」式のメンタルモデルに誘い込まれてしまうのです。
私たちは、エフェクトをコンポーネントの視点から考えてしまう理由について時間をかけて調査し、その一因が依存配列にあると考えるようになりました。常に目の前にあって書かなければならないもののため、コードが何に「反応」しているのかを意識せざるを得ず、だから「これらの値が変わったらこれを行え」式のメンタルモデルに誘い込まれてしまうのです。
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

あったほうが良い主語を補いました。

原文:

We spent some time researching why Effects are thought of from the component perspective, and we think one of the reasons is the dependency array. Since you have to write it, it's right there and in your face reminding you of what you're "reacting" to and baiting you into the mental model of 'do this when these values change'.


フックをリリースした当時から、事前コンパイルでこの使いやすさを改善できることは分かっていました。React Compiler を使用すると、ほとんどの場合、自分で `useCallback` や `useMemo` を書く必要がなくなります。エフェクトの場合、コンパイラが依存配列を自動的に挿入できるようになります。

Expand All @@ -14302,7 +14302,7 @@ useEffect(() => {
}); // compiler inserted dependencies.
```

このコードでは、依存配列を React Compiler が自動的に推論して挿入するため、見たり書いたりする必要がありません。[IDE 拡張](#compiler-ide-extension)や [`useEffectEvent`](/reference/react/useEffectEvent) のような機能を使用することで、デバッグが必要なときや依存値を削除して最適化したい時のために、コンパイラが挿入したものを表示する CodeLens を提供できます。これにより、エフェクトを書くための正しいメンタルモデルが強化され、コンポーネントやフックの state を他のものと同期させるために任意のタイミングで実行できるエフェクトが書けるようになるでしょう
このコードでは、依存配列を React Compiler が自動的に推論して挿入するため、見たり書いたりする必要がありません。[IDE 拡張](#compiler-ide-extension)や [`useEffectEvent`](/reference/react/useEffectEvent) のような機能を使用することで、デバッグが必要なときや依存値を削除して最適化したい時のために、コンパイラが挿入したものを表示する CodeLens を提供できます。これにより、エフェクトを書くための正しいメンタルモデル、つまり、エフェクトはコンポーネントやフックの state を他のものと同期させるためにいつでも実行されうる、というメンタルモデルが補強されます
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. "which can run at any time" は(僕のリアクトのメンタルモデルに照らし合わせると)どちらかというと不随意的なニュアンスなので、日本語に訳すなら「任意〜できる」よりも「いつでも〜されうる」のほうが適切だと思います。
    • たぶん誤: 「ユーザーランド上のコードから、hoge() のように呼び出し可能(随意的)」
    • たぶん正: 「React という『システム側』が自動的に実行する(不随意的)」
  2. これは、which の構文上の先行詞は Effects なので、元のほうでも良いように見えるのですが、なんだか、それだけではなく「the mental model」が意味的な先行詞になった同格表現といも取れる、ダブルミーニングっぽい感じなので、そのようになおしてみました。
    • あと、1. を考慮して訳そうと思うと、このように解釈しないと収まりがよくならないかも…

原文:

(前半略)This helps reinforce the correct mental model for writing Effects, which can run at any time to synchronize your component or hook's state with something else.


依存配列の自動挿入について我々が期待しているのは、ただ書きやすくなるというだけのことではありません。コンポーネントのライフサイクルではなく「エフェクトが何をするのか」という視点で考えることを強制し、理解がしやすくなることを期待しています。

Expand Down