En React 17, la función de limpieza de efectos siempre se ejecuta de forma asíncrona; por ejemplo, si el componente se está desmontando, la limpieza se ejecuta después de que se haya actualizado la pantalla.
En el registro de cambios , el equipo de React ha resaltado un problema potencial y una solución para esto:
Código problemático:
useEffect(() => { someRef.current.someSetupMethod(); return () => { someRef.current.someCleanupMethod(); }; });
Solución sugerida por el equipo de React:
El problema es que
someRef.current
es mutable, por lo que cuando se ejecuta la función de limpieza, es posible que se haya establecido en nulo. La solución es capturar cualquier valor mutable dentro del efecto.
useEffect(() => { const instance = someRef.current; instance.someSetupMethod(); return () => { instance.someCleanupMethod(); }; });
Si bien la solución anterior funciona en la mayoría de los casos, he creado un enlace personalizado, donde esta solución es problemática:
function useMountEffect(funcForMount, funcForUnmount) { const funcRef = useRef(); funcRef.current = { funcForMount, funcForUnmount }; useEffect(() => { funcRef?.current?.funcForMount?.(); return () => funcRef?.current?.funcForUnmount?.(); }, []); }
En el ejemplo anterior, explícitamente no quiero capturar el valor mutable, de lo contrario, tendré que volver a ejecutar el efecto cuando cambie funcForUnmount
.
La razón para crear el enlace de esta manera es tener la libertad de llamar a la función solo en el montaje/desmontaje sin preocuparse por el cierre obsoleto y la matriz de dependencia.
Actualización: he encontrado un enfoque para useMountEffect
function useMountEffect(funcForMount, funcForUnmount) { const isMounted = useRef(); useEffect(() => { return () => { isMounted.current = false; }; }, []); useEffect(() => { if (!isMounted.current) { isMounted.current = true; funcForMount?.(); } return () => !isMounted.current && funcForUnmount?.(); }); }
Pero las principales preguntas aquí son para ' El problema es que someRef.current es mutable, por lo que en el momento en que se ejecuta la función de limpieza, es posible que se haya establecido en nulo. ':
ref.current
volverse nula entre el desmontaje y la llamada de limpieza en React 17?ref.current
en nulo? ¿O es el usuario quien puede cambiar en el medio?