ampproject / ampproject/amp-react-prototype
A safe useEffect for refs
- Langage dominant
- JavaScript
- Étoiles
- 36
- Forks
- 6
- Métriques de merge des PR
- Aucune PR mergée en 30 j
Description
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.
Guide de contribution
Ouvrir le guide de contribution
Piste de recherche
Commencez par les patterns useEffect et ref présentés dans l’issue, y compris les alternatives basées sur l’état et useEffectWithRef. Comparez leur gestion des changements de ref et du nettoyage ; l’issue n’identifie ni fichier cible, ni test, ni implémentation convenue, et aucune définition de terminé n’est donc spécifiée.
Rédigé par le modèle d'indexation à partir du texte de l'issue.
Évaluation
- Stack technique
- javascript, react
- Domaine
- frontend
- Type d'issue
- Fonctionnalité
- Difficulté
- 5/5
- Temps estimé
- Plus d'une semaine
- Activité
- À l'abandon
- Clarté
- À clarifier
- Accessibilité débutants
- 25/100