Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

302
Visualizações
Reaccionar useEffect Hook cuando solo cambia una de las deps del efecto, pero no las otras

Tengo un componente funcional usando Hooks:

 function Component(props) { const [ items, setItems ] = useState([]); // In a callback Hook to prevent unnecessary re-renders const handleFetchItems = useCallback(() => { fetchItemsFromApi().then(setItems); }, []); // Fetch items on mount useEffect(() => { handleFetchItems(); }, []); // I want this effect to run only when 'props.itemId' changes, // not when 'items' changes useEffect(() => { if (items) { const item = items.find(item => item.id === props.itemId); console.log("Item changed to " item.name); } }, [ items, props.itemId ]) // Clicking the button should NOT log anything to console return ( <Button onClick={handleFetchItems}>Fetch items</Button> ); }

El componente obtiene algunos items en el montaje y los guarda en el estado.

El componente recibe una propiedad itemId (de React Router).

Siempre que cambie props.itemId , quiero que esto active un efecto, en este caso, registrándolo en la consola.


El problema es que, dado que el efecto también depende de los items , el efecto también se ejecutará cada vez que cambien los items , por ejemplo, cuando items vuelvan a recuperar presionando el botón.

Esto se puede solucionar almacenando el props.itemId anterior en una variable de estado separada y comparando los dos, pero esto parece un truco y agrega repetitivo. Usando clases de componentes, esto se resuelve comparando accesorios actuales y anteriores en componentDidUpdate , pero esto no es posible usando componentes funcionales, que es un requisito para usar Hooks.


¿Cuál es la mejor manera de activar un efecto que depende de múltiples parámetros, solo cuando uno de los parámetros cambia?


PD. Los ganchos son algo nuevo, y creo que todos estamos haciendo todo lo posible para descubrir cómo trabajar correctamente con ellos, así que si mi forma de pensar sobre esto te parece incorrecta o incómoda, indícalo.

over 4 years ago · Santiago Trujillo
3 Respostas
Responde à pergunta

0

El equipo de React dice que la mejor manera de obtener valores previos es usar useRef: https://reactjs.org/docs/hooks-faq.html#how-to-get-the-previous-props-or-state

 function Component(props) { const [ items, setItems ] = useState([]); const prevItemIdRef = useRef(); useEffect(() => { prevItemIdRef.current = props.itemId; }); const prevItemId = prevItemIdRef.current; // In a callback Hook to prevent unnecessary re-renders const handleFetchItems = useCallback(() => { fetchItemsFromApi().then(setItems); }, []); // Fetch items on mount useEffect(() => { handleFetchItems(); }, []); // I want this effect to run only when 'props.itemId' changes, // not when 'items' changes useEffect(() => { if(prevItemId !== props.itemId) { console.log('diff itemId'); } if (items) { const item = items.find(item => item.id === props.itemId); console.log("Item changed to " item.name); } }, [ items, props.itemId ]) // Clicking the button should NOT log anything to console return ( <Button onClick={handleFetchItems}>Fetch items</Button> ); }

Creo que esto podría ayudar en tu caso.

Nota: si no necesita el valor anterior, otro enfoque es escribir un useEffect más para props.itemId

 React.useEffect(() => { console.log('track changes for itemId'); }, [props.itemId]);
over 4 years ago · Santiago Trujillo Relatório

0

Una salida fácil es escribir un enlace personalizado para ayudarnos con eso.

 // Desired hook function useCompare (val) { const prevVal = usePrevious(val) return prevVal !== val } // Helper hook function usePrevious(value) { const ref = useRef(); useEffect(() => { ref.current = value; }); return ref.current; }

y luego usarlo en useEffect

 function Component(props) { const hasItemIdChanged = useCompare(props.itemId); useEffect(() => { if(hasItemIdChanged) { // … } }, [props.itemId, hasItemIdChanged]) return <></> }
over 4 years ago · Santiago Trujillo Relatório

0

⚠️ NOTA : esta respuesta actualmente es incorrecta y podría generar errores/efectos secundarios inesperados. La variable useCallback tendría que ser una dependencia del gancho useEffect , lo que conduciría al mismo problema al que se enfrentaba OP.

lo abordaré lo antes posible

Recientemente me encontré con esto en un proyecto, y nuestra solución fue mover el contenido de useEffect a una devolución de llamada (memorizada en este caso) y ajustar las dependencias de ambos. Con su código proporcionado se ve algo como esto:

 function Component(props) { const [ items, setItems ] = useState([]); const onItemIdChange = useCallback(() => { if (items) { const item = items.find(item => item.id === props.itemId); console.log("Item changed to " item.name); } }, [items, props.itemId]); // I want this effect to run only when 'props.itemId' changes, // not when 'items' changes useEffect(onItemIdChange, [ props.itemId ]); // Clicking the button should NOT log anything to console return ( <Button onClick={handleFetchItems}>Fetch items</Button> ); }

Entonces, useEffect solo tiene el ID prop como su dependencia, y la devolución de llamada tanto los elementos como el ID.

De hecho, podría eliminar la dependencia de ID de la devolución de llamada y pasarla como un parámetro a la devolución de llamada onItemIdChange :

 const onItemIdChange = useCallback((id) => { if (items) { const item = items.find(item => item.id === id); console.log("Item changed to " item.name); } }, [items]); useEffect(() => { onItemIdChange(props.itemId) }, [ props.itemId ])
over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda