Heim
» Grundvallarþekking
»
Hvernig á að laga villuna “Cannot Read Properties of Undefined (Reading map)” í React
Hvernig á að laga villuna “Cannot Read Properties of Undefined (Reading map)” í React
React-villan Cannot read properties of undefined (reading 'map') þýðir að JavaScript reyndi að meta eitthvað eins og items.map(...) þegar items var undefined. Mikilvægasti hlutinn er ekki orðið map; heldur gildið sem kemur strax fyrir framan .map().
Núverandi React-skjölun (React 19.2 þegar þetta var skrifað) notar enn JavaScript-fallið map() fyrir fylki sem staðlaðan hátt til að breyta safn í JSX-element. MDN skilgreinir Array.prototype.map() sem aðferð sem býr til nýtt fylki með því að beita callback-falli á hvert stak. Ef gildið sem þú búist við að sé fylki hefur ekki verið frumstillt, hefur ekki hlaðist enn, eða kemur úr óvæntu API-sniði, getur kallið mistekist áður en React getur teiknað listann. Sjá leiðbeiningar React um að teikna lista og MDN tilvísun í Array.prototype.map().
Dæmi um aðstæður: vörulisti sem hrynur áður en API-ið lýkur
Þetta er ímynduð dæmi til útskýringar, ekki raunverulegt prófunarniðurstaða. Ímyndaðu þér lítinn verslunarhluta (component) sem sækir vörur eftir að hlutinn birtist í fyrsta skipti. Forritarinn skrifar:
Í fyrstu teiknun er productsundefined vegna þess að engin upphafsgildi var gefið til useState. Skjölun React um useState segir að ástandsgildið í fyrstu teiknun samsvari upphafsástandinu sem þú gefur upp. Fetch-kallið keyrir síðar, svo teiknunin getur náð í products.map(...) áður en svarið berst. React useState tilvísun.
AI-búin til myndskreyting af JavaScript-villunni sem vísar á listateiknun sem kallar .map() á undefined-gildi.
Skref 1: Finndu nákvæmlega hvaða gildi er undefined
Byrjaðu á stack trace og finndu línuna sem inniheldur .map(). Í dæminu um component er sú lína products.map(...), svo products er fyrsta gildið sem þarf að skoða. Í stærri component gæti mistekna segðin verið data.items.map(), props.users.map(), eða response.results.map().
Notaðu vafra debuggerinn eða tímabundið log strax á undan teiknaralogíkinni:
Þetta aðgreinir nokkrar villur sem líta eins út í UI. Ef gildið er undefined, rannsakaðu frumstillingu eða vantar eigind. Ef það er null, gæti hleðsla/gagnalíkanið þitt notað null skýrt. Ef það er hlutur (object), gætirðu verið að lesa rangt stig úr API-svari. Ef það er strengur eða tala, er gagnasamningurinn uppstraums ólíkur því sem componentinn búist við.
Ekki skipta sjálfkrafa út öllum misteknum segðum fyrir optional chaining áður en þú skilur gildið. Það getur haldið niðri á hruninu en skilið rangt gagnaflæði eftir á.
Skref 2: Frumstilltu safn-ástand sem safn þegar það passar við líkanið þitt
Fyrir ímynduða vörulistann er tómt fylki skynsamlegt upphafsástand vegna þess að “engar vörur hlaðnar enn” má örugglega tákna sem safn með núll stökum:
const [products, setProducts] = useState([]);
Nú getur fyrsta teiknunin keyrt products.map(...) vegna þess að tómt fylki hefur map aðferð. Þegar beiðnin uppfærir síðar ástandið, teiknar React aftur með skilaðum vörum.
AI-búin til myndskreyting af frumstillingu listaástands með useState([]) svo fyrsta teiknunin hafi fylki.
Þetta er sterk lausn þegar ástandið er hugmyndafræðilega alltaf fylki. Það er síður hentugt þegar undefined eða null ber merkingarbæra upplýsingar, svo sem “ekki beðið enn,” á meðan [] þýðir “beiðnin lauk og það eru núll niðurstöður.” Í því tilviki, haltu ástöndunum aðskildum og teiknaðu hleðslu, villu og tómar aðstæður skýrt.
Skref 3: Staðfestu snið API-svarsins áður en þú setur það í ástand
Frumstilling lagar aðeins fyrstu teiknun. Hún verndar ekki componentinn ef netþjónninn skilar að lokum öðru sniði. Gerum ráð fyrir að API-ið skili í raun:
Þá geymir setProducts(data) hlut (object), ekki fylki. Líkleg villa breytist í eitthvað eins og products.map is not a function. Rétt úthlutun væri setProducts(data.products), að gefnu að það eigind sé tryggt að sé fylki.
Fyrir gögn sem fara yfir ytri mörk, staðfestu þau:
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);
});
AI-búin til myndskreyting af vörð við listateiknun með Array.isArray() áður en .map() er notað.
Þetta skiptir máli vegna þess að “öruggt sjálfgefið gildi” ætti ekki að breyta gölluðum framleiðslugögnum í þögult tóma síðu. Ef fylki er krafist í samningnum, getur skráning eða birting villu verið gagnlegri en að breyta öllum óvæntum svörum í [].
Skref 4: Veldu rétta teiknaravörð fyrir gögn sem geta lögmætt vantað
React styður venjulega JavaScript skilyrðisbundna teiknun. Opinberu skjölin sýna notkun á if, ternary segðum og && til að ákveða hvaða JSX að skila. Leiðbeiningar React um skilyrðisbundna teiknun.
Fyrir ímynduðu vörusíðuna er skýr hleðslu- og villuferli oft skýrast:
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>
);
Optional chaining er einnig gilt þegar “vantar í augnablikinu” ætti einfaldlega að skila engri kortlagðri niðurstöðu:
MDN útskýrir að optional chaining (?.) stöðvar keyrslu (short-circuits) þegar gildið vinstra megin við það er null eða undefined í stað þess að kasta TypeError. MDN tilvísun í optional chaining.
AI-búin til myndskreyting af optional chaining með users?.map(...) fyrir gögn sem geta tímabundið verið undefined.
Takmörkunin er mikilvæg: products?.map(...) kemur í veg fyrir þessa tilteknu nullish-access villu, en það sannar ekki að products sé fylki. Ef products verður að hlut (object), leysist products?.map enn upp í undefined eigind og tilraun til að kalla það getur mistekist. Notaðu schema staðfestingu eða Array.isArray() þegar gagnagerðin sjálf er óviss.
Hvaða lagfæringu ættirðu að velja?
Aðstæður
Besta fyrsta skrefið
Afhverju
Ástand ætti alltaf að vera listi
useState([])
Gefur fyrstu teiknuninni rétta gagnagerð.
Vantandi gögn hafa merkingarbæra hleðsluástand
Skilyrðisbundin teiknun
Heldur “ekki hlaðið” aðskildu frá “hlaðið en tómt.”
API snið getur verið breytilegt eða gallað
Staðfestu með Array.isArray() eða schema
Kemur í veg fyrir að slæm ytri gögn fari inn í component ástand óvarlega.
Prop er valfrjálst eftir hönnun
Optional chaining eða sjálfgefið prop gildi
Kemur í veg fyrir að afvita (dereference) lögmætt fráverandi gildi.
Villa kemur fram eftir endurskipulagningu (refactor)
Athugaðu eiginda- og prop nöfn
Endurnefnt svæði getur gert áður gilt fylki að undefined.
Algengar aðstæður sem líta út eins og sama villan
API-ið skilar { items: [...] }, en componentinn búist við fylki
Skoðaðu Network svarið og úthlutaðu fylki-eigindinu í stað umgjörðarhlutarins (wrapper object). Ekki giska á sniðið út frá gömlu dæmi eða TypeScript interface ef lifandi svarið er öðruvísi.
Með response.data.items.map(...), getur hvaða innbyggða millistigs eigind sem vantar valdið mistökum. Optional chaining eins og response?.data?.items er gagnlegt til að lesa óviss innbyggð gildi, en staðfestu lokasafnið áður en þú meðhöndlar það sem fylki.
Fyrsta teiknunin á sér stað áður en fetch Effect lýkur
React Effects keyra eftir teiknun. Skjölun React tekur einnig fram að handvirk söfnun gagna inni í Effects er algengt í client-side forritum en getur haft galla eins og waterfalls, vantar server-rendered gögn, og handvirka caching/race-condition vinnu. Ef þú notar React framework, getur innbyggður gagna-hleðslumekanismi þess verið betri arkitektúrval. React useEffect tilvísun.
Öruggari lokauðgáfa af dæminu um component
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>
);
}
Þessi útgáfa greinir á milli “ekki hlaðið,” “mistókst,” “tómt,” og “hefur gögn.” Það er orðflóknara en ein optional-chain segð, en það gefur notandanum merkingarbæran UI fyrir hvert ástand og gerir gallað API svar sýnilegt við debugging.
Fljótleg athugunarlisti áður en þú lítur á villuna sem lagaða
Athugaðu nákvæmlega hvaða gildi er strax fyrir framan .map().
Staðfestu gildi þess og gerð í teiknuninni sem mistekst.
Frumstilltu listaástand með [] þegar tómt fylki táknar upphafsástandið nákvæmlega.
Athugaðu hvort API-ið skili fylki beint eða pakki því inn í hlut-eigind.
Staðfestu ytri gögn áður en þú geymir þau í ástandi þegar samningurinn skiptir máli.
Notaðu hleðsluástand ef undefined þýðir “ekki hlaðið enn.”
Notaðu optional chaining þegar frávera er lögmæt, ekki sem staðgengil fyrir skilning á slæmum gögnum.
Athugaðu endurnefnd eða sleppt props eftir endurskipulagningar.
Gefðu teiknuðum listastökum stöðug lykla (keys) úr gögnunum, eins og mælt er með í skjölun React um listateiknun.
Fyrir ímynduða vörulistann var rót villunnar sú að fyrsta teiknunin fékk undefined þar sem componentinn bjóst strax við fylki. Í raunverulegu forriti getur sama villuskilaboð komið frá ástand frumstillingu, props, innbyggðum eigindum, eða API gögnum. Lagfærðu gagnasamninginn fyrst, veldu síðan teiknaravörð sem táknar nákvæmlega hvað “vantar” þýðir í UI þínu.