Kā novērst kļūdu “Cannot Read Properties of Undefined (Reading map)” React vidē

React kļūda Cannot read properties of undefined (reading 'map') nozīmē, ka JavaScript mēģināja izpildīt kodu, piemēram, items.map(...), kamēr items bija undefined (nenoteikts). Svarīgākā daļa nav vārds map; tā ir vērtība, kas atrodas tieši pirms .map().

Pašreizējā React dokumentācija (React 19.2 rakstīšanas brīdī) joprojām izmanto JavaScript masīva map() metodi kā standarta veidu, kā pārvērst kolekcijas JSX elementos. MDN definē Array.prototype.map() kā metodi, kas izveido jaunu masīvu, piemērojot atgriezenisko zvanu katram elementam. Ja vērtība, kuru sagaidāt esam masīvu, nav inicializēta, vēl nav ielādēta vai nāk no negaidītas API struktūras, izsaukums var neizdoties, pirms React spēj renderēt sarakstu. Skatiet React ceļvedi sarakstu renderēšanā un MDN Array.prototype.map() atsauces dokumentāciju.

Ilustratīvs scenārijs: produktu saraksts, kas sabrūk, pirms API ir pabeidzis darbību

Tas ir hipotētisks piemērs skaidrojumam, nevis reāls testa rezultāts. Iedomājieties mazu veikala komponenti, kas ielādē produktus pēc tam, kad komponente pirmo reizi parādās. Izstrādātājs raksta:

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

Pirmajā renderēšanas reizē products ir undefined, jo useState netika nodota sākotnējā vērtība. React useState dokumentācija norāda, ka stāvokļa vērtība pirmajā renderēšanā atbilst jūsu norādītajam sākotnējam stāvoklim. Pieprasījums tiek veikts vēlāk, tāpēc renderēšana var sasniegt products.map(...), pirms atbilde ir saņemta. React useState atsauce.

AI ģenerēta ilustrācija, kurā redzama pārlūka konsole ar kļūdu Cannot read properties of undefined reading map React komponentē.
AI ģenerēta ilustrācija par JavaScript kļūdu, kas norāda uz saraksta renderēšanu, kurā tiek izsaukts .map() uz nenoteiktas vērtības.

1. solis: Atrodiet precīzi, kura vērtība ir undefined

Sāciet ar steka izsekošanu (stack trace) un atrodiet rindu, kurā ir .map(). Ilustratīvajā komponentē šī rinda ir products.map(...), tāpēc products ir pirmā vērtība, kas jāpārbauda. Lielākā komponentē kļūdainā izteiksme varētu būt data.items.map(), props.users.map() vai response.results.map().

Izmantojiet pārlūka atkļūdotāju vai pagaidu žurnalizēšanu tieši pirms renderēšanas loģikas:

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

Tas ļauj atšķirt vairākas kļūdas, kas UI izskatās līdzīgas. Ja vērtība ir undefined, izpētiet inicializāciju vai trūkstošu īpašību. Ja tā ir null, jūsu ielādes/datu modelis var apzināti izmantot null. Ja tā ir objekts, iespējams, jūs lasāt nepareizu API atbildes līmeni. Ja tā ir virkne vai skaitlis, augšējā datu līguma struktūra atšķiras no tā, ko komponente sagaida.

Nemainiet automātiski katru kļūdaino izteiksmi ar neobligātu ķēdēšanu (optional chaining), pirms nesaprotat vērtību. Tas var nomākt sabrukumu, atstājot nepareizu datu plūsmu.

2. solis: Inicializējiet kolekcijas stāvokli kā kolekciju, ja tas atbilst jūsu modelim

Hipotētiskajam produktu sarakstam tukšs masīvs ir saprātīgs sākotnējais stāvoklis, jo “produkti vēl nav ielādēti” var droši attēlot kā kolekciju ar null elementiem:

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

Tagad pirmajā renderēšanā var izpildīt products.map(...), jo tukšam masīvam ir map metode. Kad pieprasījums vēlāk atjaunina stāvokli, React atkārtoti renderē ar atgrieztajiem produktiem.

AI ģenerēta ilustrācija par React useState deklarāciju, kas inicializēta ar tukšu masīvu.
AI ģenerēta ilustrācija par saraksta stāvokļa inicializāciju ar useState([]), lai pirmajā renderēšanā būtu masīvs.

Tas ir spēcīgs risinājums, ja stāvoklis konceptuāli vienmēr ir masīvs. Tas ir mazāk piemērots, ja undefined vai null nes nozīmīgu informāciju, piemēram, “vēl nav pieprasīts”, kamēr [] nozīmē “pieprasījums pabeigts un rezultātu nav”. Šādā gadījumā saglabājiet stāvokļus atšķirīgus un skaidri renderējiet ielādes, kļūdu un tukšuma nosacījumus.

3. solis: Pārbaudiet API atbildes struktūru pirms tās ievietošanas stāvoklī

Inicializācija novērš tikai pirmo renderēšanu. Tā neaizsargās komponenti, ja serveris galu galā atgriež citu struktūru. Pieņemsim, ka API patiesībā atgriež:

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

Tad setProducts(data) saglabā objektu, nevis masīvu. Visticamākā kļūda mainās uz kaut ko tādu kā products.map is not a function. Pareizā piešķiršana būtu setProducts(data.products), ja ir garantēts, ka šī īpašība ir masīvs.

Datiem, kas šķērso ārēju robežu, validējiet tos:

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 ģenerēta ilustrācija par React komponenti, kas pārbauda Array.isArray pirms map izsaukšanas.
AI ģenerēta ilustrācija par saraksta renderēšanas aizsardzību ar Array.isArray() pirms .map() izmantošanas.

Tas ir svarīgi, jo “droša noklusējuma vērtība” nedrīkst pārvērst nepareizus ražošanas datus par klusi tukšu lapu. Ja saskaņā ar līgumu ir nepieciešams masīvs, kļūdas žurnalizēšana vai parādīšana var būt noderīgāka nekā katras negaidītās atbildes pārvēršana par [].

4. solis: Izvēlieties pareizo renderēšanas aizsardzību datiem, kuru var legitīmi trūkt

React atbalsta parasto JavaScript nosacīto renderēšanu. Oficiālajā dokumentācijā parādīts, kā izmantot if, ternāros izteikumus un &&, lai noteiktu, kādu JSX atgriezt. React nosacītās renderēšanas ceļvedis.

Hipotētiskajai produktu lapai skaidra ielādes un kļūdu plūsma bieži vien ir saprotamākā:

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

Neobligāta ķēdēšana ir derīga arī tad, ja “pagaidām nav pieejams” vienkārši nedrīkst radīt kartētu rezultātu:

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

MDN paskaidro, ka neobligāta ķēdēšana (?.) pārtrauc izpildi, ja vērtība tās kreisajā pusē ir null vai undefined, tā vietā, lai izmestu TypeError. MDN neobligātās ķēdēšanas atsauce.

AI ģenerēta ilustrācija par neobligātu ķēdēšanu, kas izmantota pirms map React komponentē.
AI ģenerēta ilustrācija par neobligātu ķēdēšanu ar users?.map(...) datiem, kas var īslaicīgi būt undefined.

Ierobežojums ir svarīgs: products?.map(...) novērš šo konkrēto nullish piekļuves kļūdu, taču tas nepierāda, ka products ir masīvs. Ja products kļūst par objektu, products?.map joprojām atrisinās uz nenoteiktu īpašību, un mēģinājums to izsaukt var neizdoties. Izmantojiet shēmas validāciju vai Array.isArray(), ja pats datu tips ir neskaidrs.

Kuru risinājumu izvēlēties?

SituācijaLabākais pirmais solisKāpēc
Stāvoklim vienmēr jābūt sarakstamuseState([])Sniedz pirmajai renderēšanai pareizo datu tipu.
Trūkstošiem datiem ir nozīmīgs ielādes stāvoklisNosacīta renderēšanaSaglabā “nav ielādēts” atšķirīgu no “ielādēts, bet tukšs”.
API struktūra var mainīties vai būt nepareizaValidējiet ar Array.isArray() vai shēmuNovērš sliktu ārēju datu iekļūšanu komponentes stāvoklī nepamanīti.
Prop ir pēc dizaina neobligātsNeobligāta ķēdēšana vai noklusējuma prop vērtībaIzvairās no leģitīmi trūkstošas vērtības atsauces atšifrēšanas.
Kļūda parādās pēc refaktoraPārbaudiet īpašību un prop nosaukumusPārdēvēts lauks var padarīt agrāk derīgu masīvu par undefined.

Bieži gadījumi, kas izskatās pēc tās pašas kļūdas

API atgriež { items: [...] }, bet komponente sagaida masīvu

Pārbaudiet tīkla atbildi un piešķiriet masīva īpašību, nevis ietvarojošo objektu. Nespējiet struktūru pēc veca piemēra vai TypeScript interfeisa, ja dzīvā atbilde atšķiras.

Vecāku komponente aizmirst nodot prop

Tas neizdosies:

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

// Parent accidentally omits users:
<UserList />

Ja izlaistam propam jānozīmē tukšs saraksts, noklusējums padara šo līgumu skaidru:

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

Trūkst ligzdotas īpašības

Izmantojot response.data.items.map(...), jebkura trūkstoša starpposma īpašība var izraisīt kļūdu. Neobligāta ķēdēšana, piemēram, response?.data?.items, ir noderīga neskaidru ligzdotu vērtību lasīšanai, taču validējiet galīgo kolekciju, pirms uzskatāt to par masīvu.

Pirmā renderēšana notiek pirms fetch Effect pabeigšanas

React Effects tiek izpildīti pēc renderēšanas. React dokumentācija arī norāda, ka manuāla datu ielādēšana Effects iekšienē ir izplatīta klienta puses lietotnēs, taču tai var būt trūkumi, piemēram, ūdenskritumi, trūkstoši servera renderēti dati un manuāla kešēšanas/sacensību apstrāde. Ja izmantojat React ietvaru, tā iebūvētais datu ielādes mehānisms var būt labāks arhitektūras izvēles punkts. React useEffect atsauce.

Drošāka ilustratīvās komponentes gala versija

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

Šī versija apzināti atšķir “nav ielādēts”, “neizdevās”, “tukšs” un “ir dati”. Tas ir apjomīgāk nekā viena neobligātas ķēdēšanas izteiksme, taču tas sniedz lietotājam nozīmīgu UI katram stāvoklim un padara nepareizu API atbildi redzamu atkļūdošanas laikā.

Ātra pārbaudes saraksta pirms uzskatāt, ka kļūda ir novērsta

  • Identificējiet precīzo vērtību tieši pirms .map().
  • Apstipriniet tās vērtību un tipu renderēšanā, kas neizdodas.
  • Inicializējiet saraksta stāvokli ar [], ja tukšs masīvs precīzi attēlo sākotnējo stāvokli.
  • Pārbaudiet, vai API atgriež masīvu tieši vai ietver to objekta īpašībā.
  • Validējiet ārējos datus pirms to saglabāšanas stāvoklī, ja līgums ir svarīgs.
  • Izmantojiet ielādes stāvokli, ja undefined nozīmē “vēl nav ielādēts”.
  • Izmantojiet neobligātu ķēdēšanu, ja trūkums ir leģitīms, nevis kā aizstājēju sliktu datu izpratnei.
  • Pārbaudiet pārdēvētus vai izlaistus props pēc refaktoriem.
  • Nodrošiniet renderētajiem saraksta elementiem stabilas atslēgas no datiem, kā ieteicams React sarakstu renderēšanas dokumentācijā.

Hipotētiskajam produktu sarakstam pamatcēlonis bija pirmā renderēšana, kas saņēma undefined, kur komponente nekavējoties sagaidīja masīvu. Reālā lietotnē tā pati kļūdas ziņa var rasties no stāvokļa inicializācijas, props, ligzdotām īpašībām vai API datiem. Vispirms novērsiet datu līguma problēmu, pēc tam izvēlieties renderēšanas aizsardzību, kas precīzi attēlo, ko “trūkstošs” nozīmē jūsu UI.

Atstājiet komentāru

Kā novērst kļūdu "ENOSPC: sasniegts failu vērotāju sistēmas ierobežojums" operētājsistēmā Linux

Kā novērst kļūdu "ENOSPC: sasniegts failu vērotāju sistēmas ierobežojums" operētājsistēmā Linux

Novērsiet Linux ENOSPC failu vērotāja kļūdas, pārbaudot inotify ierobežojumus, atrodot procesus, kuros ir daudz vērotāja resursu, droši paaugstinot ierobežojumus un padarot izmaiņas pastāvīgas.

Kā novērst kļūdu “Tailwind CSS stili netiek atjaunināti” Vite React lietotnē

Kā novērst kļūdu “Tailwind CSS stili netiek atjaunināti” Vite React lietotnē

Novērsiet Tailwind CSS stilu neatjaunināšanu pakalpojumā Vite React, pārbaudot Tailwind v4 iestatījumus, CSS importēšanu, avota noteikšanu, dinamiskās klases, HMR un novecojušas kešatmiņas.

Kā novērst ModuleNotFoundError kļūdu: Python 3 nav moduļa ar nosaukumu “pip”

Kā novērst ModuleNotFoundError kļūdu: Python 3 nav moduļa ar nosaukumu “pip”

Novērsiet Python 3 ModuleNotFoundError kļūdu pip funkcijai operētājsistēmās Windows, macOS un Linux, izmantojot ensurepip, OS pakotnes, virtuālās vides un interpretētāja pārbaudes.

Kā GitHub SSH novērst kļūdu "Atļauja liegta (publiskā atslēga)"

Kā GitHub SSH novērst kļūdu "Atļauja liegta (publiskā atslēga)"

Novērsiet GitHub SSH atļaujas liegšanu (publiskā atslēga), pārbaudot resursdatoru, aktīvo SSH atslēgu, GitHub kontu, SSO autorizāciju, attālo URL un 22. porta piekļuvi.

Kā novērst kļūdu “Git Push noraidīts: nepārtīšana uz priekšu”, nezaudējot izmaiņas

Kā novērst kļūdu “Git Push noraidīts: nepārtīšana uz priekšu”, nezaudējot izmaiņas

Droši izlabojiet Git ne-ātrās pārtīšanas kļūdu. Aizsargājiet lokālo darbu, ielādējiet attālinātus izmaiņu izmaiņu ierakstus, izvēlieties apvienošanu vai atkārtotu bāzi, atrisiniet konfliktus un veiciet izmaiņu pārtīšanu, nezaudējot izmaiņas.

Kā novērst kļūdu "Nginx 502 Bad Gateway", veicot starpniekservera darbību ar Node.js

Kā novērst kļūdu "Nginx 502 Bad Gateway", veicot starpniekservera darbību ar Node.js

Izlabojiet Nginx 502 Bad Gateway kļūdas ar Node.js augšupējo resursu, pārbaudot lietotnes portu, NGINX žurnālus, proxy_pass adresi, konteineru tīklošanu, taimautus un atkārtotu ielādi.

Kā TypeScript labot kļūdu “Type 'null' nav piešķirams tipam”

Kā TypeScript labot kļūdu “Type 'null' nav piešķirams tipam”

Novērsta TypeScript kļūda “Tips 'null' nav piešķirams tipam”, izmantojot apvienošanas tipus, sašaurināšanu, noklusējuma vērtības un drošas apgalvojumus, izmantojot strictNullChecks.

Kā novērst kļūdu “Prisma Client has not been generated yet”

Kā novērst kļūdu “Prisma Client has not been generated yet”

Novērsiet Prisma Client ģenerēšanas kļūdu, pārbaudot savu ģeneratoru, shēmu, izvades ceļu, importus, versijas, monorepo iestatījumu un izvietošanas būvēšanas soļus.

Kā novērst kļūdu "ERR_MODULE_NOT_FOUND" Node.js ESM importā

Kā novērst kļūdu "ERR_MODULE_NOT_FOUND" Node.js ESM importā

Izlabojiet Node.js ERR_MODULE_NOT_FOUND kļūdu ESM, pārbaudot importēšanas ceļus, failu paplašinājumus, pakotņu instalēšanu, eksportēšanu, ESM režīmu un tīrās instalācijas.

Kā novērst SSL sertifikāta problēmu: Nevar iegūt vietējo izdevēja sertifikātu Git

Kā novērst SSL sertifikāta problēmu: Nevar iegūt vietējo izdevēja sertifikātu Git

Novērsiet Git kļūdu “nevar iegūt vietējo izdevēja sertifikātu”, identificējot uzticības aizmugurprogrammu, instalējot pareizo CA ķēdi un saglabājot SSL verifikāciju iespējotu.