Kako riješiti grešku “Cannot Read Properties of Undefined (Reading map)” u Reactu

Reactova greška Cannot read properties of undefined (reading 'map') znači da je JavaScript pokušao procijeniti nešto poput items.map(...) dok je items bilo undefined. Važan dio nije riječ map; to je vrijednost koja se nalazi neposredno prije .map().

Trenutna React dokumentacija (React 19.2 u vrijeme pisanja) i dalje koristi JavaScriptovu metodu polja map() kao standardni način pretvaranja kolekcija u JSX elemente. MDN definira Array.prototype.map() kao metodu koja stvara novi niz primjenom povratnog poziva na svaki element. Ako vrijednost koju očekujete da bude niz nije inicijalizirana, još nije učitana ili dolazi iz neočekivanog oblika API odgovora, poziv može ne uspijeti prije nego što React može prikazati popis. Pogledajte Reactov vodič za prikazivanje popisa i MDN referencu za Array.prototype.map().

Ilustrativni scenarij: popis proizvoda koji se ruši prije nego što API završi

Ovo je hipotetski primjer za objašnjenje, a ne stvarni rezultat testa. Zamislite malu komponentu trgovine koja dohvaća proizvode nakon što se komponenta prvi put pojavi. Programer piš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>
  );
}

Prilikom prvog prikaza, products je undefined jer početna vrijednost nije proslijeđena u useState. Dokumentacija za Reactov useState navodi da vrijednost stanja pri prvom prikazu odgovara početnom stanju koje navedete. Dohvaćanje se izvršava naknadno, pa prikaz može doći do products.map(...) prije nego što odgovor stigne. React useState referenca.

Ilustracija generirana AI-jem koja prikazuje konzolu preglednika s greškom Cannot read properties of undefined reading map u React komponenti.
Ilustracija generirana AI-jem koja prikazuje JavaScript grešku koja ukazuje na prikaz popisa koji poziva .map() na vrijednosti undefined.

Korak 1: Pronađite točno koja je vrijednost undefined

Počnite od tragova poziva (stack trace) i pronađite redak koji sadrži .map(). U ilustrativnoj komponenti, taj redak je products.map(...), pa je products prva vrijednost koju treba pregledati. U većoj komponenti, neispravni izraz mogao bi biti data.items.map(), props.users.map() ili response.results.map().

Koristite debugger preglednika ili privremeni zapis neposredno prije logike prikaza:

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

Ovo razdvaja nekoliko grešaka koje u korisničkom sučelju izgledaju slično. Ako je vrijednost undefined, istražite inicijalizaciju ili nedostajuće svojstvo. Ako je null, vaš model učitavanja/podataka možda eksplicitno koristi null. Ako je objekt, možda čitate pogrešnu razinu API odgovora. Ako je niz znakova ili broj, ugovor o podacima gore u nizu razlikuje se od onoga što komponenta očekuje.

Nemojte automatski zamijeniti svaki neispravni izraz opcionalnim povezivanjem (optional chaining) prije nego što razumijete vrijednost. To može prikriti rušenje programa, a da pritom ostavi netočan tok podataka.

Korak 2: Inicijalizirajte stanje kolekcije kao kolekciju kada to odgovara vašem modelu

Za hipotetski popis proizvoda, prazan niz je razumna početna vrijednost jer se “još nema učitanih proizvoda” može sigurno predstaviti kao kolekcija s nula stavki:

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

Sada prvi prikaz može izvršiti products.map(...) jer prazan niz ima metodu map. Kada zahtjev naknadno ažurira stanje, React ponovno prikazuje s vraćenim proizvodima.

Ilustracija generirana AI-jem koja prikazuje deklaraciju React useState inicijaliziranu praznim nizom.
Ilustracija generirana AI-jem koja prikazuje inicijalizaciju stanja popisa s useState([]) kako bi prvi prikaz imao niz.

Ovo je snažno rješenje kada je stanje konceptualno uvijek niz. Manje je prikladno kada undefined ili null nose značajne informacije, poput “još nije zatraženo”, dok [] znači “zahtjev je završen i nema rezultata”. U tom slučaju, držite stanja odvojenima i eksplicitno prikažite uvjete učitavanja, greške i praznog stanja.

Korak 3: Provjerite oblik API odgovora prije nego što ga stavite u stanje

Inicijalizacija rješava samo prvi prikaz. Neće zaštititi komponentu ako poslužitelj na kraju vrati drugačiju strukturu. Pretpostavimo da API zapravo vraća:

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

Tada setProducts(data) sprema objekt, a ne niz. Vjerojatna greška mijenja se u nešto poput products.map is not a function. Ispravna dodjela bila bi setProducts(data.products), pod uvjetom da je to svojstvo zajamčeno da bude niz.

Za podatke koji prelaze vanjsku granicu, validirajte ih:

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);
  });
Ilustracija generirana AI-jem koja prikazuje React komponentu koja provjerava Array.isArray prije poziva map.
Ilustracija generirana AI-jem koja prikazuje zaštitu prikaza popisa s Array.isArray() prije korištenja .map().

Ovo je važno jer “sigurna zadana vrijednost” ne bi trebala pretvoriti neispravne produkcijske podatke u tiho praznu stranicu. Ako ugovor zahtijeva niz, bilježenje ili prikazivanje greške može biti korisnije od pretvaranja svakog neočekivanog odgovora u [].

Korak 4: Odaberite pravu zaštitu pri prikazu za podatke koji mogu legitimno nedostajati

React podržava normalno JavaScript uvjetno prikazivanje. Službena dokumentacija pokazuje korištenje if, ternarnih izraza i && za odlučivanje koji JSX vratiti. React vodič za uvjetno prikazivanje.

Za hipotetsku stranicu proizvoda, eksplicitan tok učitavanja i greške često je najjasniji:

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>
);

Opcionalno povezivanje također je valjano kada “trenutno nedostaje” jednostavno treba proizvesti nema mapiranog rezultata:

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

MDN objašnjava da opcionalno povezivanje (?.) prekida izvršavanje kada je vrijednost lijevo od njega null ili undefined, umjesto da baca TypeError. MDN referenca za opcionalno povezivanje.

Ilustracija generirana AI-jem koja prikazuje opcionalno povezivanje korišteno prije map u React komponenti.
Ilustracija generirana AI-jem koja prikazuje opcionalno povezivanje s users?.map(...) za podatke koji mogu privremeno biti undefined.

Ograničenje je važno: products?.map(...) sprječava ovu specifičnu grešku pristupa nullish vrijednosti, ali ne dokazuje da je products niz. Ako products postane objekt, products?.map i dalje se rješava na undefined svojstvo i pokušaj poziva može ne uspijeti. Koristite validaciju sheme ili Array.isArray() kada je sama vrsta podataka nesigurna.

Koje rješenje biste trebali odabrati?

SituacijaNajbolji prvi potezZašto
Stanje bi uvijek trebalo biti popisuseState([])Daje prvom prikazu ispravnu vrstu podataka.
Nedostajući podaci imaju značajno stanje učitavanjaUvjetno prikazivanjeDrži “nije učitano” odvojenim od “učitano, ali prazno”.
Oblik API-ja može varirati ili biti neispravanValidirajte s Array.isArray() ili shemomSprječava da loši vanjski podaci neprimijećeni uđu u stanje komponente.
Prop je opcionalan po dizajnuOpcionalno povezivanje ili zadana vrijednost propaIzbjegava dereferenciranje legitimno odsutne vrijednosti.
Greška se pojavljuje nakon refaktoriranjaProvjerite nazive svojstava i propovaPreimenovano polje može učiniti da nekada valjan niz postane undefined.

Uobičajeni slučajevi koji izgledaju kao ista greška

API vraća { items: [...] }, ali komponenta očekuje niz

Pregledajte odgovor mreže i dodijelite svojstvo niza, a ne objekt omotač. Nemojte nagađati oblik iz starog primjera ili TypeScript sučelja ako se stvarni odgovor razlikuje.

Nadređena komponenta zaboravi proslijediti prop

Ovo će ne uspijeti:

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

// Parent accidentally omits users:
<UserList />

Ako izostavljeni prop treba značiti prazan popis, zadana vrijednost čini taj ugovor eksplicitnim:

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

Nedostaje ugniježđeno svojstvo

S response.data.items.map(...), bilo koje nedostajuće posredno svojstvo može uzrokovati neuspjeh. Opcionalno povezivanje poput response?.data?.items korisno je za čitanje nesigurnih ugniježđenih vrijednosti, ali validirajte konačnu kolekciju prije nego što je tretirate kao niz.

Prvi prikaz događa se prije nego što Effect dohvaćanja završi

React Effects izvršavaju se nakon prikaza. Reactova dokumentacija također napominje da je ručno dohvaćanje podataka unutar Effects uobičajeno u klijentskim aplikacijama, ali može imati nedostatke poput kaskadnih zahtjeva (waterfalls), nedostajućih podataka server-side renderiranja i ručnog rada s predmemorijom/uvjetima utrkivanja. Ako koristite React okvir, njegova ugrađena mehanizam za učitavanje podataka može biti bolji arhitektonski izbor. React useEffect referenca.

Sigurnija konačna verzija ilustrativne komponente

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>
  );
}

Ova verzija namjerno razlikuje “nije učitano”, “neuspjelo”, “prazno” i “ima podataka”. To je opširnije od jednog izraza opcionalnog povezivanja, ali korisniku daje značajno korisničko sučelje za svako stanje i čini neispravan API odgovor vidljivim tijekom otklanjanja grešaka.

Brzi popis provjera prije nego što smatrate da je greška riješena

  • Identificirajte točnu vrijednost neposredno prije .map().
  • Potvrdite njezinu vrijednost i vrstu pri prikazu koji ne uspijeva.
  • Inicijalizirajte stanje popisa s [] kada prazan niz točno predstavlja početno stanje.
  • Provjerite vraća li API niz izravno ili ga omata u svojstvo objekta.
  • Validirajte vanjske podatke prije spremanja u stanje kada je ugovor važan.
  • Koristite stanje učitavanja ako undefined znači “još nije učitano”.
  • Koristite opcionalno povezivanje kada je odsutnost legitimna, a ne kao zamjenu za razumijevanje loših podataka.
  • Provjerite preimenovane ili izostavljene propove nakon refaktoriranja.
  • Dajte prikazanim stavkama popisa stabilne ključeve iz podataka, kako preporučuje Reactova dokumentacija za prikazivanje popisa.

Za hipotetski popis proizvoda, uzrok je bio prvi prikaz koji je primio undefined tamo gdje je komponenta odmah očekivala niz. U stvarnoj aplikaciji, ista poruka o grešci može potjecati od inicijalizacije stanja, propova, ugniježđenih svojstava ili API podataka. Prvo popravite ugovor o podacima, a zatim odaberite zaštitu pri prikazu koja točno predstavlja što “nedostaje” znači u vašem korisničkom sučelju.

Ostavite komentar

Kako popraviti grešku "Tailwind CSS stilovi se ne ažuriraju" u Vite React aplikaciji

Kako popraviti grešku "Tailwind CSS stilovi se ne ažuriraju" u Vite React aplikaciji

Ispravite Tailwind CSS stilove koji se ne ažuriraju u Vite Reactu provjerom postavki Tailwind v4, CSS uvoza, otkrivanja izvora, dinamičkih klasa, HMR-a i zastarjelih predmemorija.

Kako popraviti ModuleNotFoundError: Nema modula pod nazivom 'pip' u Pythonu 3

Kako popraviti ModuleNotFoundError: Nema modula pod nazivom 'pip' u Pythonu 3

Ispravite ModuleNotFoundError u Pythonu 3 za pip na Windowsima, macOS-u i Linuxu pomoću ensurepipa, OS paketa, virtualnih okruženja i provjera interpretera.

Kako popraviti "Dozvola odbijena (javni ključ)" u GitHub SSH-u

Kako popraviti "Dozvola odbijena (javni ključ)" u GitHub SSH-u

Ispravite GitHub SSH Permission Denied (publickey) provjerom hosta, aktivnog SSH ključa, GitHub računa, SSO autorizacije, udaljenog URL-a i pristupa portu 22.

Kako popraviti "Git Push Rejected: Non-FastForward" bez gubitka promjena

Kako popraviti "Git Push Rejected: Non-FastForward" bez gubitka promjena

Sigurno ispravite Git push koji ne omogućuje brzo premotavanje. Zaštitite lokalni rad, dohvatite udaljene commitove, odaberite spajanje ili rebase, riješite sukobe i pushajte bez gubitka promjena.

Kako popraviti "Nginx 502 Bad Gateway" prilikom proxyja za Node.js

Kako popraviti "Nginx 502 Bad Gateway" prilikom proxyja za Node.js

Ispravite greške Nginx 502 Bad Gateway s Node.js uzvodno provjerom porta aplikacije, NGINX logova, proxy_pass adrese, umrežavanja kontejnera, vremenskih ograničenja i ponovnog učitavanja.

Kako popraviti "Tip 'null' se ne može dodijeliti tipu" u TypeScriptu

Kako popraviti "Tip 'null' se ne može dodijeliti tipu" u TypeScriptu

Ispravljena je greška "Tip 'null' nije moguće dodijeliti tipu" u TypeScriptu s tipovima unija, sužavanjem, zadanim vrijednostima i sigurnim tvrdnjama pod strictNullChecks.

Kako ispraviti pogrešku „Prisma Client has not been generated yet”

Kako ispraviti pogrešku „Prisma Client has not been generated yet”

Ispravite pogrešku da Prisma Client nije generiran provjerom generatora, sheme, izlazne putanje, uvoza, verzija, monorepo postavki i koraka izgradnje pri implementaciji.

Kako ispraviti "ERR_MODULE_NOT_FOUND" u Node.js ESM uvozima

Kako ispraviti "ERR_MODULE_NOT_FOUND" u Node.js ESM uvozima

Ispravite Node.js ERR_MODULE_NOT_FOUND u ESM-u provjerom putanja uvoza, ekstenzija datoteka, instalacije paketa, izvoza, ESM načina rada i čistih instalacija.

Kako riješiti problem sa SSL certifikatom: Nemoguće dobiti lokalni certifikat izdavatelja u Gitu

Kako riješiti problem sa SSL certifikatom: Nemoguće dobiti lokalni certifikat izdavatelja u Gitu

Riješite Gitovu grešku 'nemoguće dobiti lokalni certifikat izdavatelja' identificiranjem pozadine povjerenja, instaliranjem ispravnog lanca CA i održavanjem omogućene SSL verifikacije.

Kako riješiti grešku mrežnog isteka vremena MongoDB u Mongoose vezi

Kako riješiti grešku mrežnog isteka vremena MongoDB u Mongoose vezi

Riješite greške mrežnog isteka vremena MongoDB u Mongooseu identificiranjem vrste isteka, testiranjem dostupnosti Atlasa ili TCP-a, ispravljanjem URI-ja i podešavanjem vremena isteka samo kada je opravdano.