Es básicamente una página donde agrego esas pequeñas aplicaciones que he creado a lo largo de este camino de desarrollo web. Todas ellas, primeramente, fueron creadas puramente con HTML y CSS. A medida que fueron avanzando mis conocimientos, pasé aNextJs con React.
Para este proyecto usé como base las siguientes tecnologías:
Este texto está escrito en un archivo markdown convertido a mdx. La razón principal de convertirlo fue que este último me permitía darle estilos y agregar componentes de React.
Al igual que de la misma forma me permite renderizar codigos como:
export default function Home() {
return <h1>Hello</h1>
}Es un Client Component de Next.js encargado de gestionar toda la interacción del usuario con el listado de personajes de Los Simpson.
Este componente sigue una separación clara de responsabilidades:
Esta organización facilita el mantenimiento del código, mejora la reutilización de componentes y permite que cada uno tenga una única responsabilidad dentro de la aplicación.
El comportamiento del componente puede resumirse en el siguiente flujo:
SimpsonsClient.SimpsonCard) por cada personaje.handleOpen.getSimpsonById.selected se actualiza con los nuevos datos.SimpsonModal recibe el personaje seleccionado y muestra toda su información.null y el modal desaparece.Mientras que el servidor obtiene la lista inicial de personajes y la envía como propiedad (props), este componente se ocupa de renderizar las tarjetas, manejar los eventos de clic y mostrar la información detallada de cada personaje dentro de un modal.
La directiva:
'use client'indica que este componente se ejecutará en el navegador. Esto es necesario porque utiliza Hooks de React (useState) y responde a eventos del usuario, funcionalidades que únicamente pueden ejecutarse del lado del cliente.
El componente recibe un arreglo de personajes mediante la propiedad simpsons.
type Props = {
simpsons: Simpson[]
}Esto significa que el componente no realiza la petición inicial de datos, sino que recibe la información ya preparada desde un Server Component, aprovechando el renderizado del servidor para mejorar el rendimiento y el SEO.
Para controlar el personaje seleccionado se utiliza el Hook useState.
const [selected, setSelected] = useState<SimpsonDetail | null>(null)Este estado almacena dos posibles valores:
null: cuando no existe ningún personaje seleccionado y el modal permanece cerrado.SimpsonDetail: cuando se obtiene la información completa de un personaje y debe mostrarse el modal.Cada vez que cambia este estado, React vuelve a renderizar el componente para reflejar la nueva información en pantalla.
Cuando el usuario hace clic sobre una tarjeta se ejecuta la función handleOpen.
const handleOpen = async (id: number) => {
const data = await getSimpsonById(id)
setSelected(data)
}Su funcionamiento es el siguiente:
getSimpsonById(id), una función asíncrona que obtiene toda la información disponible de ese personaje.await.selected.Al actualizar el estado, React renderiza nuevamente el componente y el modal recibe automáticamente la información del personaje seleccionado.
El listado de personajes se construye recorriendo el arreglo recibido mediante map.
{simpsons.map((s) => (
<div key={s.id} onClick={() => handleOpen(s.id)}>
<SimpsonCard simpson={s} />
</div>
))}Cada elemento del arreglo genera una tarjeta independiente.
En cada iteración:
key={s.id} para que React pueda identificar correctamente cada elemento de la lista.onClick que ejecuta handleOpen.SimpsonCard, responsable únicamente de mostrar la información básica del personaje.De esta manera, SimpsonsClient delega la presentación visual de cada tarjeta a un componente independiente, manteniendo una arquitectura modular y fácil de mantener.
Al final del componente se renderiza siempre el modal.
<SimpsonModal
simpson={selected}
onClose={() => setSelected(null)}
/>El modal recibe dos propiedades:
simpson: contiene el personaje seleccionado.onClose: función que restablece el estado a null.Cuando el usuario cierra el modal, se ejecuta:
setSelected(null)Al volver el estado a null, el modal deja de mostrar información y desaparece de la interfaz.
Las tarjetas se muestran dentro de un contenedor con clases de Tailwind CSS.
<div className="grid gap-6 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">La distribución cambia automáticamente según el tamaño de la pantalla:
Esto permite que la interfaz se adapte correctamente tanto a dispositivos móviles como a pantallas de escritorio.
Esta aplicación es un Todo List moderno construido con Next.js (App Router) + React Client Components, utilizando:
useStatelocalStorage