ampproject / ampproject/amp-react-prototype

A safe useEffect for refs

オープン
#55 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る
主要言語
JavaScript
スター
36
フォーク
6
PR マージ指標
30日以内にマージされた PR はありません

説明

The pattern:

```
const ref = useRef();
useEffect(() => {
ref.current.addEventListener(...);
return () => ref.current.removeEventListener(...);
}, [...])

return (


{props.mode === 1 ? : }

);
```

In this pattern, it's hard to react safely to changes of `ref.current`, e.g. when a node mapped to it is deleted/changes. The "right" way to do this is to ensure that the `deps` array contains the same condition that affects `ref`. E.g. `[props.mode]` in the example above. However, it's not always obvious and easy to miss.

Some solutions are below.

/1/ Ask nicely for `deps` to be correct and hope for the best

Hopefully an "exhaustive deps" linter would not remove the extra dep.

/2/ Ban changing of Ref mapping.

I.e. disallow the example above. This could be hard with `forwardRef`.

/3/ Use state function instead of ref:

```
const [node, setNode] = useState();
useEffect(() => {...}, [node])
return <...>
```

The negative: it forces the second rerender each time the ref changes.

/4/ Use a funky `xEffectWithRef` version.

It'd manage the `ref` value internally and could look something like this:

```
function useEffectWithRef(ref, effect, deps) {
const unsubscribe = useRef(null);
const prev = useRef(null);
useEffect(() => {
return () => doUnsubscribe(prev, unsubscribe);
}, deps || []);
useEffect(() => {
const {current} = ref;
if (current !== prev.current) {
doUnsubscribe(prev, unsubscribe);
prev.current = current;
if (current) {
unsubscribe.current = effect(current);
}
}
});
}
```

The positive: it doesn't cause rerender.
A negative: one effect is executed each time, but it will almost always do nothing.

コントリビューションガイド

コントリビューションガイドを開く

調査の方向性

issue に示されている useEffect と ref のパターンから始め、state-based と useEffectWithRef の代替案も含めます。それらが ref の変更とクリーンアップをどのように扱うかを比較します。issue では対象ファイル、テスト、合意された実装のいずれも特定されていないため、Definition of Done は指定されていません。

索引モデルが issue の本文から書いたものです。

評価

技術スタック
javascript, react
領域
frontend
issue の種類
機能追加
難易度
5/5
見積もり時間
1週間以上
活発さ
停滞
明瞭さ
説明が足りない
初心者へのやさしさ
25/100

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。