Curso react nivel medio
Introducción
useTransition es un hook de React diseñado para manejar transiciones de estado de forma más fluida, especialmente en aplicaciones donde cambios de estado complejos pueden causar bloqueos en la interfaz de usuario. Este hook permite clasificar actualizaciones como urgentes o no urgentes, asegurando que la interfaz mantenga su interactividad mientras React procesa los cambios.
¿Qué es useTransition?
- Propósito: Manejar actualizaciones no urgentes, como filtros o animaciones, que no deben bloquear la UI.
- Estado dual:
- Actualizaciones urgentes: Responden de inmediato, como clics o entradas de texto.
- Actualizaciones no urgentes: Procesan tareas más complejas, como cálculos o filtrado.
Sintaxis
1const [isPending, startTransition] = useTransition();
isPending: Booleano que indica si la transición está en progreso.startTransition: Función que encapsula la lógica de actualización no urgente.
Ejemplo Básico: Transición de Estado
Código
1import React, { useState, useTransition } from "react"; 2 3function ListaPesada() { 4 const [filtro, setFiltro] = useState(""); 5 const [lista, setLista] = useState([]); 6 const [isPending, startTransition] = useTransition(); 7 8 const manejarCambio = (e) => { 9 const valor = e.target.value; 10 setFiltro(valor); 11 12 startTransition(() => { 13 const nuevaLista = Array.from({ length: 20000 }, (_, i) => `Elemento ${i}`) 14 .filter((item) => item.includes(valor)); 15 setLista(nuevaLista); 16 }); 17 }; 18 19 return ( 20 <div> 21 <input 22 type="text" 23 value={filtro} 24 onChange={manejarCambio} 25 placeholder="Filtrar lista" 26 /> 27 {isPending && <p>Cargando...</p>} 28 <ul> 29 {lista.map((item, index) => ( 30 <li key={index}>{item}</li> 31 ))} 32 </ul> 33 </div> 34 ); 35} 36 37export default ListaPesada;
Explicación
isPending:- Muestra un mensaje de "Cargando..." mientras la lista se actualiza.
startTransition:- Encapsula la lógica de filtrado para que sea una actualización no urgente.
- Rendimiento Mejorado:
- La entrada del usuario sigue respondiendo de forma inmediata mientras se procesa la actualización.
Caso Práctico: Filtro en una Tabla
Código
1import React, { useState, useTransition } from "react"; 2 3function Tabla() { 4 const [filtro, setFiltro] = useState(""); 5 const [datos, setDatos] = useState( 6 Array.from({ length: 10000 }, (_, i) => ({ 7 id: i, 8 nombre: `Nombre ${i}`, 9 })) 10 ); 11 const [resultados, setResultados] = useState(datos); 12 const [isPending, startTransition] = useTransition(); 13 14 const manejarFiltro = (e) => { 15 const valor = e.target.value; 16 setFiltro(valor); 17 18 startTransition(() => { 19 const nuevosResultados = datos.filter((item) => 20 item.nombre.toLowerCase().includes(valor.toLowerCase()) 21 ); 22 setResultados(nuevosResultados); 23 }); 24 }; 25 26 return ( 27 <div> 28 <input 29 type="text" 30 value={filtro} 31 onChange={manejarFiltro} 32 placeholder="Filtrar por nombre" 33 /> 34 {isPending && <p>Filtrando datos...</p>} 35 <table> 36 <thead> 37 <tr> 38 <th>ID</th> 39 <th>Nombre</th> 40 </tr> 41 </thead> 42 <tbody> 43 {resultados.map((item) => ( 44 <tr key={item.id}> 45 <td>{item.id}</td> 46 <td>{item.nombre}</td> 47 </tr> 48 ))} 49 </tbody> 50 </table> 51 </div> 52 ); 53} 54 55export default Tabla;
Explicación
- Filtrar Datos:
startTransitionencapsula la lógica de filtrado para evitar bloquear la entrada del usuario.
isPending:- Muestra un indicador mientras se actualiza la tabla.
- Eficiencia:
- La tabla no se vuelve a renderizar hasta que la transición haya completado el filtrado.
Diferencias con useDeferredValue
| Característica | useTransition | useDeferredValue |
|---|---|---|
| Propósito | Clasificar actualizaciones como urgentes o no urgentes | Diferir el valor para actualizaciones no urgentes |
Indicador (isPending) | Sí | No |
| Uso Común | Actualizaciones complejas que afectan el estado | Retrasar actualizaciones de UI con datos procesados |
Limitaciones de useTransition
-
Solo para Actualizaciones de Estado:
- Solo funciona para diferir actualizaciones de estado, no para tareas generales como fetch de datos.
-
Diseñado para Fluidez:
- No mejora directamente el rendimiento en cálculos costosos; solo mantiene la UI interactiva.
-
Dependiente del Código Reactivo:
- No sustituye optimizaciones manuales como memoización o división de carga.
Buenas Prácticas con useTransition
-
Evitar Sobreuso:
- No encapsules todas las actualizaciones; úsalo solo para tareas no urgentes que afecten la experiencia del usuario.
-
Combinar con Memoización:
- Usa
React.memoouseMemopara evitar renderizados innecesarios.
- Usa
-
Indicadores Claros:
- Proporciona retroalimentación visual usando
isPendingpara mostrar el progreso.
- Proporciona retroalimentación visual usando
Ejemplo Completo: Filtro y Contador Simultáneo
Código
1import React, { useState, useTransition } from "react"; 2 3function App() { 4 const [contador, setContador] = useState(0); 5 const [filtro, setFiltro] = useState(""); 6 const [lista, setLista] = useState( 7 Array.from({ length: 10000 }, (_, i) => `Elemento ${i}`) 8 ); 9 const [resultados, setResultados] = useState(lista); 10 const [isPending, startTransition] = useTransition(); 11 12 const manejarFiltro = (e) => { 13 const valor = e.target.value; 14 setFiltro(valor); 15 16 startTransition(() => { 17 const nuevosResultados = lista.filter((item) => 18 item.toLowerCase().includes(valor.toLowerCase()) 19 ); 20 setResultados(nuevosResultados); 21 }); 22 }; 23 24 return ( 25 <div> 26 <h1>Ejemplo Completo</h1> 27 <button onClick={() => setContador((prev) => prev + 1)}> 28 Incrementar Contador ({contador}) 29 </button> 30 <input 31 type="text" 32 value={filtro} 33 onChange={manejarFiltro} 34 placeholder="Filtrar lista" 35 /> 36 {isPending && <p>Filtrando...</p>} 37 <ul> 38 {resultados.map((item, index) => ( 39 <li key={index}>{item}</li> 40 ))} 41 </ul> 42 </div> 43 ); 44} 45 46export default App;
Explicación
- Estado Urgente:
- El contador responde de inmediato.
- Estado No Urgente:
- La lista se actualiza con una transición, manteniendo fluidez.
Conclusión
useTransition es una herramienta poderosa para manejar actualizaciones no urgentes, mejorando la fluidez en aplicaciones complejas. Úsalo para:
- Filtros de grandes listas.
- Tareas costosas que no deben bloquear la UI.
- Actualizaciones visuales que pueden esperar.