useEffect
useEffect
El hook useEffect
es uno de los hooks más importantes y versátiles en React. Se utiliza para gestionar efectos secundarios en componentes funcionales, como hacer llamadas a APIs, suscribirse a servicios, actualizar el DOM, y mucho más.
Nota: Se recomienda no usarlo como cambios directos a elementos de escucha (es mejor usar un onClick) y para traer datos de lugares externos, que se recomienda usar (React query[https://www.npmjs.com/package/react-query]) o la herramienta del propio (framework[https://nextjs.org/])
-
Importación: Primero, necesitas importar el hook desde React.
import React, { useEffect } from 'react' -
Sintaxis básica:
useEffect(() => {// Código del efectoreturn () => {// Código de limpieza (opcional)}}, [dependencies])- Función de efecto: Se ejecuta después de que el componente se monte y después de cada actualización si las dependencias han cambiado.
- Función de limpieza (opcional): Se ejecuta antes de que el componente se desmonte o antes de ejecutar el efecto la próxima vez.
- Dependencias: Una lista de variables que, si cambian, harán que el efecto se vuelva a ejecutar.
Ejemplo Básico
Imaginemos que queremos hacer una llamada a una API para obtener datos cuando el componente se monta.
import React, { useState, useEffect } from 'react'
function DataFetcher() { const [data, setData] = useState(null)
useEffect(() => { // Efecto: Hacer una llamada a una API fetch('https://api.example.com/data') .then((response) => response.json()) .then((data) => setData(data)) }, []) // Dependencias vacías significa que esto solo se ejecuta al montar
return ( <div> <h1>Fetched Data</h1> {data ? <pre>{JSON.stringify(data, null, 2)}</pre> : <p>Loading...</p>} </div> )}
export default DataFetcher
Desglose del Ejemplo
-
Estado Inicial:
const [data, setData] = useState(null)Se utiliza
useState
para almacenar los datos obtenidos de la API. -
Efecto de
useEffect
:useEffect(() => {fetch('https://api.example.com/data').then((response) => response.json()).then((data) => setData(data))}, [])El
useEffect
hace una llamada a la API cuando el componente se monta. Las dependencias vacías ([]
) aseguran que esto solo ocurra una vez.
Limpieza de Efectos
Cuando el efecto implica una suscripción o algún recurso que debe limpiarse, puedes devolver una función de limpieza.
Ejemplo con Suscripción
Imaginemos que tenemos un servicio de suscripción a un WebSocket que necesitamos limpiar cuando el componente se desmonte.
import React, { useState, useEffect } from 'react'
function WebSocketComponent() { const [messages, setMessages] = useState([])
useEffect(() => { const socket = new WebSocket('ws://example.com/socket')
socket.addEventListener('message', (event) => { setMessages((prevMessages) => [...prevMessages, event.data]) })
// Función de limpieza return () => { socket.close() } }, []) // Dependencias vacías significa que esto solo se ejecuta al montar
return ( <div> <h1>Messages</h1> <ul> {messages.map((msg, index) => ( <li key={index}>{msg}</li> ))} </ul> </div> )}
export default WebSocketComponent
Desglose del Ejemplo de Limpieza
-
Efecto de
useEffect
con Limpieza:useEffect(() => {const socket = new WebSocket('ws://example.com/socket')socket.addEventListener('message', (event) => {setMessages((prevMessages) => [...prevMessages, event.data])})return () => {socket.close()}}, [])- La conexión WebSocket se crea al montar el componente.
- Se añade un listener para recibir mensajes.
- Se devuelve una función de limpieza que cierra el WebSocket cuando el componente se desmonte.
Efectos con Dependencias
Los efectos pueden depender de variables que cambian. Imaginemos que queremos hacer una nueva llamada a una API cada vez que cambie una variable query
.
import React, { useState, useEffect } from 'react'
function SearchComponent() { const [query, setQuery] = useState('react') const [results, setResults] = useState([])
useEffect(() => { if (query) { fetch(`https://api.example.com/search?q=${query}`) .then((response) => response.json()) .then((data) => setResults(data.results)) } }, [query]) // Ejecuta el efecto cuando `query` cambia
return ( <div> <input type="text" value={query} onChange={(e) => setQuery(e.target.value)} /> <ul> {results.map((result, index) => ( <li key={index}>{result.name}</li> ))} </ul> </div> )}
export default SearchComponent
Desglose del Ejemplo con Dependencias
- Dependencia
query
:El efecto se ejecuta cada vez queuseEffect(() => {if (query) {fetch(`https://api.example.com/search?q=${query}`).then((response) => response.json()).then((data) => setResults(data.results))}}, [query])query
cambia, haciendo una nueva llamada a la API y actualizando los resultados.