ampproject / ampproject/amp-react-prototype

A safe useEffect for refs

Abierto
#55 0 comentarios 0 reacciones 0 asignados Ver en GitHub
Lenguaje dominante
JavaScript
Estrellas
36
Forks
6
Métricas de merge de PR
Sin PR fusionados en 30 d

Descripción

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.

Guía de contribución

Abrir la guía de contribución

Línea de trabajo

Comienza con los patrones de useEffect y ref mostrados en el issue, incluidas las alternativas basadas en estado y useEffectWithRef. Compara cómo gestionan los cambios de ref y la limpieza; el issue no identifica un archivo de destino, una prueba ni una implementación acordada, por lo que no se especifica una definición de terminado.

Escrito por el modelo de indexación a partir del texto del issue.

Evaluación

Stack tecnológico
javascript, react
Área
frontend
Tipo de issue
Nueva funcionalidad
Dificultad
5/5
Tiempo estimado
Más de una semana
Estado de actividad
Estancado
Claridad
Necesita aclaración
Aptitud para principiantes
25/100

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.