Si queremos restringir useEffect
para que se ejecute solo cuando se monta el componente, podemos agregar un segundo parámetro de useEffect
con []
.
useEffect(() => { // ... }, []);
Pero, ¿cómo podemos hacer que useEffect
se ejecute solo en el momento en que se actualiza el componente, excepto el montaje inicial?
Si desea que useEffect se ejecute solo en las actualizaciones, excepto en el montaje inicial, puede utilizar useRef
para realizar un seguimiento de initialMount con useEffect
sin el segundo parámetro.
const isInitialMount = useRef(true); useEffect(() => { if (isInitialMount.current) { isInitialMount.current = false; } else { // Your useEffect code here to be run on update } });
Me gusta mucho la respuesta de Shubham, así que hice un Hook personalizado.
/** * A custom useEffect hook that only triggers on updates, not on initial mount * @param {Function} effect * @param {Array<any>} dependencies */ export default function useUpdateEffect(effect, dependencies = []) { const isInitialMount = useRef(true); useEffect(() => { if (isInitialMount.current) { isInitialMount.current = false; } else { return effect(); } }, dependencies); }
Tanto Shubham como Mario sugieren el enfoque correcto, sin embargo, el código aún está incompleto y no considera los siguientes casos.
effect
de paso puede tener una función de limpieza devuelta, que nunca se llamaríaCompartiendo a continuación un código más completo que cubre los dos casos faltantes anteriores:
import React from 'react'; const useIsMounted = function useIsMounted() { const isMounted = React.useRef(false); React.useEffect(function setIsMounted() { isMounted.current = true; return function cleanupSetIsMounted() { isMounted.current = false; }; }, []); return isMounted; }; const useUpdateEffect = function useUpdateEffect(effect, dependencies) { const isMounted = useIsMounted(); const isInitialMount = React.useRef(true); React.useEffect(() => { let effectCleanupFunc = function noop() {}; if (isInitialMount.current) { isInitialMount.current = false; } else { effectCleanupFunc = effect() || effectCleanupFunc; } return () => { effectCleanupFunc(); if (!isMounted.current) { isInitialMount.current = true; } }; }, dependencies); // eslint-disable-line react-hooks/exhaustive-deps };