Cannot Read Properties of Undefined en React y Next.js: Solución Definitiva 2026
Soluciona TypeError: Cannot read properties of undefined (reading 'map', 'length', 'name'). Causas reales en React/Next.js, 3 soluciones con código y cómo evitarlo para siempre.
Tabla de contenidos
🎯 Lo que aprenderás en este artículo
- Por qué te pasa este error en React aunque el código parezca correcto (fetch, props, useEffect)
- 3 soluciones con código copiable: optional chaining, guard clause y fallback seguro
- Cómo evitarlo para siempre con TypeScript, Zod y tests
Es el error que más veces he visto en React, en DAW y en producción:
TypeError: Cannot read properties of undefined (reading 'map')
O su primo:
TypeError: Cannot read properties of undefined (reading 'length')
TypeError: Cannot read properties of undefined (reading 'name')
Traducción humana: intentas usar .map, .length o .name de algo que es undefined. React no puede renderizar undefined.map() y crashea toda la página en blanco.
La buena noticia: tiene 3 soluciones de 1 línea y se puede evitar para siempre con 2 hábitos.
Por qué te pasa (el 90% de los casos es uno de estos 3)
1. Los datos aún no han llegado
function UserList({ users }) {
return <ul>{users.map(u => <li key={u.id}>{u.name}</li>)}</ul>
}
// Si users viene de un fetch, el primer render es users = undefined → CRASH
En Next.js App Router es aún más común con fetch en Server Component que tarda o falla.
2. No pasaste la prop o la escribiste mal
<UserList user={users} /> // singular
// dentro: users es undefined porque la prop se llama user
3. La API devolvió otra forma
Esperas { users: [...] } pero la API devolvió { data: [...] } o null por un error 500. Tu data.users.map crashea aunque el fetch sí hizo algo.
Si no sabes qué te devuelve la API, imprime antes de mapear: console.log(data). O pega el error en mi Traductor de Errores — te lo explica en español.
Solución 1: Optional chaining ?. (rápida, para salir del paso)
La más rápida. No crashea, simplemente no renderiza nada si es undefined.
// Antes (crash)
users.map(u => <li>{u.name}</li>)
// Después (seguro)
users?.map(u => <li key={u.id}>{u.name}</li>)
// Con fallback visible
users?.length ? users.map(u => <li key={u.id}>{u.name}</li>) : <p>Sin usuarios</p>
Cuándo usarla: componente pequeño, lista opcional, prototipo rápido.
Solución 2: Guard clause (la que yo uso en producción)
La más legible. Devuelves pronto si no hay datos.
function UserList({ users }: { users?: User[] }) {
if (!users) return <p className="text-gray-500">Cargando usuarios...</p>
if (users.length === 0) return <p>No hay usuarios aún.</p>
return (
<ul>
{users.map(u => (
<li key={u.id} className="py-1">{u.name}</li>
))}
</ul>
)
}
Ventaja: el usuario ve qué pasa (cargando / vacío) en vez de una página en blanco. En Next.js evita el Error Boundary rojo.
Solución 3: Fallback seguro con ?? + valor por defecto
Ideal cuando el dato viene de props o de un fetch que puede fallar.
// Componente siempre recibe array, nunca undefined
function UserList({ users = [] }: { users?: User[] }) {
return <ul>{users.map(u => <li key={u.id}>{u.name}</li>)}</ul>
}
// Fetch con fallback
const res = await fetch('/api/users')
const data = await res.json()
const users: User[] = data.users ?? [] // si API falla, array vacío
Truco Next.js 15: si haces fetch en Server Component, valida con Zod para no fiarte de la forma:
import { z } from 'zod'
const UserSchema = z.object({ id: z.string(), name: z.string() })
const UsersResponse = z.object({ users: z.array(UserSchema) })
export default async function Page() {
const res = await fetch('https://api.com/users', { cache: 'no-store' })
const json = await res.json()
const parsed = UsersResponse.safeParse(json)
if (!parsed.success) {
return <p>Error cargando usuarios.</p>
}
return <UserList users={parsed.data.users} />
}
Así TypeScript te obliga a manejar el caso undefined antes de llegar al .map.
Tabla: qué usar y cuándo
| Caso | Solución | Código |
|---|---|---|
| Lista opcional, prototipo | ?. | users?.map(...) |
| Página / componente crítico | Guard clause | if (!users) return <Cargando/> |
| Prop que puede no venir | Default param | ({ users = [] }) |
| Fetch a API externa | Zod + fallback | data.users ?? [] |
Cómo evitarlo para siempre (2 hábitos)
Hábito 1: Tipa todo
// ❌ Mal: no sabes qué puede ser users
function UserList({ users }) { ... }
// ✅ Bien: TypeScript te avisa si puede ser undefined
type User = { id: string; name: string }
function UserList({ users }: { users: User[] | undefined }) { ... }
Si users puede ser undefined, el editor te subrayará users.map hasta que lo arregles.
Mi guía: TypeScript para JavaScript developers 2026.
Hábito 2: Valida lo que entra
No confíes en fetch. Valida:
// Antes: confías
const users = data.users // si API cambia, crash
// Después: validas
const users = z.array(UserSchema).parse(data.users) // si falla, error controlado
Más: Parsear JSON de IA sin errores y variables de entorno en Next.js.
Caso real: Next.js 15 + Prisma
Este es el caso que más veo en DAW (lista de usuarios desde base de datos):
// app/users/page.tsx — Server Component
import { prisma } from '@/lib/prisma'
import { UserList } from '@/components/UserList'
export default async function UsersPage() {
const users = await prisma.user.findMany() // siempre es array, nunca undefined
// Pero si filtras y puede venir null:
const user = await prisma.user.findUnique({ where: { id } })
// user puede ser null → no hagas user.name sin comprobar
return <UserList users={users} />
}
// components/UserList.tsx — Client Component
'use client'
type User = { id: string; name: string }
export function UserList({ users }: { users: User[] }) {
if (users.length === 0) return <p>Nadie por aquí aún.</p>
return <ul>{users.map(u => <li key={u.id}>{u.name}</li>)}</ul>
}
Prisma siempre devuelve array, pero findUnique puede devolver null. Ahí es donde aparece el reading 'name'.
Checklist debugging (cuando no sabes de dónde viene)
- Mira la línea exacta del stacktrace:
at UserList (src/components/UserList.jsx:12:24)→ línea 12, columna 24 - Pon
console.log(users)justo antes del.mapy recarga - Revisa el Network tab: ¿tu
fetchdevuelve 200 o 500? ¿Qué JSON trae? - Si el error es intermitente, es 100% dato que a veces no llega → usa guard clause
- Pega el traceback en el Traductor de Errores para ver causa y fix paso a paso, o genera un prompt con el Generador de Prompts y que la IA te dé el parche
También: Errores comunes con Copilot y Cline en VS Code y la colección completa en /blog/errores/.
¿Te sigue saliendo? Pega tu error + el componente que falla en el Traductor de Errores y te digo la línea exacta que arreglar. Si quieres que lo mire con tu repo real, link en mi portfolio y lo vemos.
Artículos relacionados
5 Animaciones con Framer Motion que Uso en Todos Mis Proyectos React
React 19: Las Novedades que Cambian tu Código en 2026
Aider: Programa con IA desde la Terminal (Alternativa Barata a Cursor)
Cómo Implementar Autenticación con Auth.js (NextAuth) Sin Volverte Loco
¿Te aparece este error?
Cannot read properties of undefined (reading 'map') Solución: Cannot read properties of undefined (reading 'map') en React
Invalid hook call. Hooks can only be called inside of a function component Solución: Invalid hook call en React — causas y solución definitiva
Objects are not valid as a React child