Ako opraviť chybu „Cannot read properties of undefined (reading 'map')“ v React

Chyba React Cannot read properties of undefined (reading 'map') znamená, že JavaScript sa pokúsil vyhodnotiť niečo ako items.map(...), pričom items bolo undefined. Dôležitou časťou nie je slovo map; je to hodnota bezprostredne pred .map().

Aktuálna dokumentácia React (React 19.2 v čase písania) stále používa JavaScriptovú metódu poľa map() ako štandardný spôsob prevodu kolekcií na JSX prvky. MDN definuje Array.prototype.map() ako metódu, ktorá vytvára nové pole aplikáciou callbacku na každý prvok. Ak hodnota, ktorú očakávate ako pole, nebola inicializovaná, ešte sa nenačítala alebo pochádza z neočakávanej štruktúry API, volanie môže zlyhať skôr, než React dokáže vykresliť zoznam. Pozrite si sprievodcu React vykresľovaním zoznamov a referenciu MDN pre Array.prototype.map().

Ilustratívny scenár: zoznam produktov, ktorý zlyhá pred dokončením požiadavky na API

Toto je hypotetický príklad na vysvetlenie, nie skutočný výsledok testu. Predstavte si malú komponentu obchodu, ktorá načítava produkty po prvom zobrazení komponenty. Vývojár napíše:

function ProductList() {
  const [products, setProducts] = useState();

  useEffect(() => {
    fetch('/api/products')
      .then(response => response.json())
      .then(data => setProducts(data));
  }, []);

  return (
    <ul>
      {products.map(product => (
        <li key={product.id}>{product.name}</li>
      ))}
    </ul>
  );
}

Pri prvom vykreslení je products undefined, pretože do useState nebola odovzdaná žiadna počiatočná hodnota. Dokumentácia useState v React uvádza, že hodnota stavu pri prvom vykreslení zodpovedá počiatočnému stavu, ktorý poskytnete. Požiadavka fetch sa spustí až následne, takže vykreslenie môže dosiahnuť products.map(...) skôr, než príde odpoveď. Referencia React useState.

Ilustrácia generovaná AI zobrazujúca konzolu prehliadača s chybovým hlásením Cannot read properties of undefined reading map v komponente React.
Ilustrácia generovaná AI zobrazujúca chybu JavaScriptu ukazujúcu na vykreslenie zoznamu, ktoré volá .map() na nedefinovanej hodnote.

Krok 1: Nájdite presne tú hodnotu, ktorá je nedefinovaná

Začnite pri zásobníku volaní (stack trace) a nájdite riadok obsahujúci .map(). V ilustračnej komponente je týmto riadkom products.map(...), takže products je prvá hodnota na preskúmanie. Vo väčšej komponente môže byť zlyhávajúcim výrazom namiesto toho data.items.map(), props.users.map() alebo response.results.map().

Použite debugger prehliadača alebo dočasný log bezprostredne pred logikou vykresľovania:

console.log('products:', products);
console.log('is array:', Array.isArray(products));

Tým rozlíšite niekoľko chýb, ktoré vyzerajú v používateľskom rozhraní podobne. Ak je hodnota undefined, preskúmajte inicializáciu alebo chýbajúcu vlastnosť. Ak je null, váš model načítania/dát môže explicitne používať null. Ak je to objekt, možno čítate nesprávnu úroveň odpovede z API. Ak je to reťazec alebo číslo, dátová zmluva od zdroja sa líši od toho, čo komponenta očakáva.

Neautomaticky nenahrádzajte každý zlyhávajúci výraz voliteľným reťazením (optional chaining) skôr, než pochopíte hodnotu. To môže potlačiť pád, ale ponechať nesprávny tok dát na mieste.

Krok 2: Inicializujte stav kolekcie ako kolekciu, ak to zodpovedá vášmu modelu

Pre hypotetický zoznam produktov je prázdne pole rozumným počiatočným stavom, pretože „žiadne produkty ešte načítané“ môže byť bezpečne reprezentované ako kolekcia s nulovým počtom položiek:

const [products, setProducts] = useState([]);

Teraz môže prvé vykreslenie spustiť products.map(...), pretože prázdne pole má metódu map. Keď požiadavka neskôr aktualizuje stav, React vykreslí znova s vrátenými produktmi.

Ilustrácia generovaná AI zobrazujúca deklaráciu useState v React inicializovanú prázdym poľom.
Ilustrácia generovaná AI zobrazujúca inicializáciu stavu zoznamu pomocou useState([]), aby prvé vykreslenie malo pole.

Toto je silné riešenie, keď je stav konceptuálne vždy pole. Je menej vhodné, keď undefined alebo null nesie významnú informáciu, napríklad „zatiaľ nevyžiadané“, zatiaľ čo [] znamená „požiadavka dokončená a sú nula výsledkov“. V takom prípade udržujte stavy odlišné a explicitne vykresľujte podmienky načítavania, chyby a prázdneho stavu.

Krok 3: Overte štruktúru odpovede API pred uložením do stavu

Inicializácia rieši iba prvé vykreslenie. Neochráni komponentu, ak server nakoniec vráti inú štruktúru. Predpokladajme, že API skutočne vráti:

{
  "products": [
    { "id": 1, "name": "Keyboard" },
    { "id": 2, "name": "Mouse" }
  ]
}

Potom setProducts(data) uloží objekt, nie pole. Pravdepodobná chyba sa zmení na niečo ako products.map is not a function. Správne priradenie by bolo setProducts(data.products), za predpokladu, že táto vlastnosť je zaručene pole.

Pre dáta prechádzajúce vonkajšou hranicou ich validujte:

fetch('/api/products')
  .then(response => response.json())
  .then(data => {
    if (!Array.isArray(data.products)) {
      throw new Error('Expected data.products to be an array');
    }
    setProducts(data.products);
  })
  .catch(error => {
    console.error(error);
    setError(error);
  });
Ilustrácia generovaná AI zobrazujúca komponentu React kontrolujúcu Array.isArray pred volaním map.
Ilustrácia generovaná AI zobrazujúca ochranu vykreslenia zoznamu pomocou Array.isArray() pred použitím .map().

To je dôležité, pretože „bezpečná predvolená hodnota“ by nemala meniť poškodené produkčné dáta na ticho prázdnu stránku. Ak je pole vyžadované zmluvou, logovanie alebo zobrazenie chyby môže byť užitočnejšie než konverzia každej neočakávanej odpovede na [].

Krok 4: Vyberte správnu ochrannú mechanizmus vykresľovania pre dáta, ktoré môžu legitímne chýbať

React podporuje bežné JavaScriptové podmienené vykresľovanie. Oficiálna dokumentácia ukazuje použitie if, ternárnych výrazov a && na rozhodnutie, aký JSX vrátiť. Sprievodca React podmieneným vykresľovaním.

Pre hypotetickú stránku produktov je explicitný tok načítavania a chyby často najjasnejší:

if (error) {
  return <p>Could not load products.</p>;
}

if (products === undefined) {
  return <p>Loading products…</p>;
}

if (products.length === 0) {
  return <p>No products found.</p>;
}

return (
  <ul>
    {products.map(product => (
      <li key={product.id}>{product.name}</li>
    ))}
  </ul>
);

Voliteľné reťazenie je tiež platné, keď „zatiaľ chýba“ by malo jednoducho vyprodukovať žiadny mapovaný výsledok:

{products?.map(product => (
  <ProductCard key={product.id} product={product} />
))}

MDN vysvetľuje, že voliteľné reťazenie (?.) sa skratuje (short-circuits), keď je hodnota na jeho ľavej strane null alebo undefined, namiesto toho, aby vyhodila TypeError. Referencia MDN pre voliteľné reťazenie.

Ilustrácia generovaná AI zobrazujúca použitie voliteľného reťazenia pred map v komponente React.
Ilustrácia generovaná AI zobrazujúca voliteľné reťazenie s users?.map(...) pre dáta, ktoré môžu byť dočasne nedefinované.

Obmedzenie je dôležité: products?.map(...) zabraňuje tejto konkrétnej chybe prístupu k nullish hodnote, ale nedokazuje, že products je pole. Ak sa products stane objektom, products?.map sa stále vyhodnotí na nedefinovanú vlastnosť a pokus o jej volanie môže zlyhať. Použite validáciu schémy alebo Array.isArray(), keď je dátový typ sám o sebe neistý.

Ktoré riešenie by ste mali zvoliť?

SituáciaNajlepšie prvé opatreniePrečo
Stav by mal byť vždy zoznamuseState([])Poskytuje prvému vykresleniu správny dátový typ.
Chýbajúce dáta majú významný stav načítavaniaPodmienené vykresľovanieUdržuje „nezačítané“ oddelené od „načítané, ale prázdne“.
Štruktúra API sa môže meniť alebo byť poškodenáValidujte pomocou Array.isArray() alebo schémyZabraňuje vstupu zlých vonkajších dát do stavu komponenty bez povšimnutia.
Prop je z návrhu voliteľnýVoliteľné reťazenie alebo predvolená hodnota propuVyhnite sa dereferencii legitímne chýbajúcej hodnoty.
Chyba sa objaví po refactoringuSkontrolujte názvy vlastností a propovPremenované pole môže spôsobiť, že kedysi platné pole sa stane nedefinovaným.

Bežné prípady, ktoré vyzerajú ako tá istá chyba

API vracia { items: [...] }, ale komponenta očakáva pole

Preskúmajte odpoveď v sieti (Network) a priraďte vlastnosť poľa, nie obalový objekt. Nehádajte štruktúru zo starého príkladu alebo rozhrania TypeScript, ak sa živá odpoveď líši.

Rodičovská komponenta zabudne odovzdať prop

Toto zlyhá:

function UserList({ users }) {
  return users.map(user => <div key={user.id}>{user.name}</div>);
}

// Parent accidentally omits users:
<UserList />

Ak by vynechaný prop mal znamenať prázdny zoznam, predvolená hodnota túto zmluvu explicitne vyjadruje:

function UserList({ users = [] }) {
  return users.map(user => <div key={user.id}>{user.name}</div>);
}

Chýba vnorená vlastnosť

Pri response.data.items.map(...) môže zlyhať akákoľvek chýbajúca medzivlastnosť. Voliteľné reťazenie ako response?.data?.items je užitočné na čítanie neistých vnorených hodnôt, ale pred spracovaním ako pole validujte konečnú kolekciu.

Prvé vykreslenie nastane skôr, než sa dokončí Effect na načítanie dát

React Effects sa spúšťajú po vykreslení. Dokumentácia React tiež uvádza, že manuálne načítanie dát vnútri Effects je bežné v klientskych aplikáciách, ale môže mať nevýhody, ako sú vodopády požiadaviek, chýbajúce dáta vykreslené na serveri a manuálna práca s cache/race conditions. Ak používate framework React, jeho vstavaný mechanizmus načítavania dát môže byť lepšou architektonickou voľbou. Referencia React useEffect.

Bezpečnejšia finálna verzia ilustračnej komponenty

import { useEffect, useState } from 'react';

export default function ProductList() {
  const [products, setProducts] = useState(undefined);
  const [error, setError] = useState(null);

  useEffect(() => {
    let ignore = false;

    fetch('/api/products')
      .then(response => {
        if (!response.ok) throw new Error('Request failed');
        return response.json();
      })
      .then(data => {
        if (!Array.isArray(data.products)) {
          throw new Error('Expected products array');
        }
        if (!ignore) setProducts(data.products);
      })
      .catch(error => {
        if (!ignore) setError(error);
      });

    return () => {
      ignore = true;
    };
  }, []);

  if (error) return <p>Could not load products.</p>;
  if (products === undefined) return <p>Loading products…</p>;
  if (products.length === 0) return <p>No products found.</p>;

  return (
    <ul>
      {products.map(product => (
        <li key={product.id}>{product.name}</li>
      ))}
    </ul>
  );
}

Táto verzia zámerne rozlišuje „nezačítané“, „zlyhané“, „prázdne“ a „má dáta“. Je to verbosejšie než jeden výraz s voliteľným reťazením, ale poskytuje používateľovi zmysluplné UI pre každý stav a robí poškodenú odpoveď API viditeľnú počas ladenia.

Rýchly kontrolný zoznam pred tým, ako považujete chybu za opravenú

  • Identifikujte presnú hodnotu bezprostredne pred .map().
  • Potvrďte jej hodnotu a typ pri vykreslení, ktoré zlyhá.
  • Inicializujte stav zoznamu pomocou [], keď prázdne pole presne reprezentuje počiatočný stav.
  • Skontrolujte, či API vracia pole priamo, alebo ho obaľuje vo vlastnosti objektu.
  • Validujte vonkajšie dáta pred uložením do stavu, keď na zmluve záleží.
  • Použite stav načítavania, ak undefined znamená „zatiaľ nezačítané“.
  • Použite voliteľné reťazenie, keď je neprítomnosť legitímna, nie ako náhradu za pochopenie zlých dát.
  • Skontrolujte premenované alebo vynechané propy po refaktoringu.
  • Dajte vykresleným položkám zoznamu stabilné kľúče z dát, ako odporúča dokumentácia React pre vykresľovanie zoznamov.

Pre hypotetický zoznam produktov bola príčinou koreňa to, že prvé vykreslenie dostalo undefined tam, kde komponenta okamžite očakávala pole. V reálnej aplikácii môže rovnaká chybová správa pochádzať z inicializácie stavu, propov, vnorených vlastností alebo dát z API. Najprv opravte dátovú zmluvu, potom vyberte ochranný mechanizmus vykresľovania, ktorý presne reprezentuje, čo „chýbajúce“ znamená vo vašom UI.

Zanechať komentár

Ako opraviť chybu „CSS štýly Tailwind sa neaktualizujú“ v aplikácii Vite React

Ako opraviť chybu „CSS štýly Tailwind sa neaktualizujú“ v aplikácii Vite React

Opravte neaktualizované štýly CSS v Tailwind vo Vite React kontrolou nastavenia Tailwind v4, importu CSS, detekcie zdrojov, dynamických tried, HMR a zastaraných vyrovnávacích pamätí.

Ako opraviť ModuleNotFoundError: V Pythone 3 neexistuje modul s názvom „pip“

Ako opraviť ModuleNotFoundError: V Pythone 3 neexistuje modul s názvom „pip“

Oprava chyby ModuleNotFoundError v jazyku Python 3 pre príkaz pip v systémoch Windows, macOS a Linux pomocou nástroja ensurepip, balíkov operačného systému, virtuálnych prostredí a kontrol interpretov.

Ako opraviť chybu „Oprávnenie zamietnuté (verejný kľúč)“ v GitHub SSH

Ako opraviť chybu „Oprávnenie zamietnuté (verejný kľúč)“ v GitHub SSH

Opravte chybu „Oprávnenie GitHub SSH zamietnuté (verejný kľúč)“ kontrolou hostiteľa, aktívneho kľúča SSH, účtu GitHub, autorizácie SSO, vzdialenej adresy URL a prístupu na port 22.

Ako opraviť chybu „Git Push Rejected: Non-FastForward“ bez straty zmien

Ako opraviť chybu „Git Push Rejected: Non-FastForward“ bez straty zmien

Bezpečne opravte nerýchle pretáčanie zmien v Gite. Chráňte lokálnu prácu, načítajte vzdialené commity, vyberte zlúčenie alebo rebase, vyriešte konflikty a odošlite zmeny bez straty.

Ako opraviť chybu „Nginx 502 Bad Gateway“ pri proxyovaní do Node.js

Ako opraviť chybu „Nginx 502 Bad Gateway“ pri proxyovaní do Node.js

Opravte chyby Nginx 502 Bad Gateway s Node.js upstream kontrolou portu aplikácie, protokolov NGINX, adresy proxy_pass, siete kontajnerov, časových limitov a opätovného načítania.

Ako opraviť chybu „Typ 'null' nie je priraditeľný k typu“ v TypeScripte

Ako opraviť chybu „Typ 'null' nie je priraditeľný k typu“ v TypeScripte

Oprava chyby „Typ 'null' nie je možné priradiť k typu“ v jazyku TypeScript pomocou typov zjednotenia, zúženia, predvolených hodnôt a bezpečných tvrdení v rámci strictNullChecks.

Ako opraviť chybu „Prisma Client has not been generated yet“

Ako opraviť chybu „Prisma Client has not been generated yet“

Opravte chybu nevygenerovaného Prisma Client kontrolou generátora, schémy, výstupnej cesty, importov, verzií, nastavenia monorepa a krokov zostavenia pri nasadení.

Ako opraviť chybu „ERR_MODULE_NOT_FOUND“ v importoch Node.js ESM

Ako opraviť chybu „ERR_MODULE_NOT_FOUND“ v importoch Node.js ESM

Opravte chybu Node.js ERR_MODULE_NOT_FOUND v ESM kontrolou ciest importu, prípon súborov, inštalácie balíkov, exportov, režimu ESM a čistých inštalácií.

Ako vyriešiť problém so SSL certifikátom: Unable to get local issuer certificate v Git

Ako vyriešiť problém so SSL certifikátom: Unable to get local issuer certificate v Git

Vyriešte chybu Git 'unable to get local issuer certificate' identifikáciou dôveryhodného backendu, inštaláciou správneho reťazca CA a ponechaním zapnutej SSL verifikácie.

Ako opraviť chybu časového limitu siete MongoDB v pripojení Mongoose

Ako opraviť chybu časového limitu siete MongoDB v pripojení Mongoose

Opravte chyby časového limitu siete MongoDB v Mongoose identifikáciou typu časového limitu, testovaním dosiahnuteľnosti Atlasu alebo TCP, opravou URI a ladením časových limitov len v odôvodnených prípadoch.