Så här åtgärdar du felet “Cannot Read Properties of Undefined (Reading map)” i React

React-felet Cannot read properties of undefined (reading 'map') innebär att JavaScript försökte utvärdera något som items.map(...) medan items var undefined. Det viktiga är inte ordet map; det är värdet omedelbart före .map().

Den aktuella React-dokumentationen (React 19.2 vid tidpunkten för skrivandet) använder fortfarande JavaScripts arraymetod map() som standardmetod för att omvandla samlingar till JSX-element. MDN definierar Array.prototype.map() som en metod som skapar en ny array genom att tillämpa en callback på varje element. Om värdet du förväntar dig ska vara en array inte har initierats, inte har laddats än eller kommer från en oväntad API-struktur, kan anropet misslyckas innan React hinner rendera listan. Se React:s guide för rendering av listor och MDN:s referens för Array.prototype.map().

Illustrativt scenario: en produktlista som kraschar innan API:t är klart

Detta är ett hypotetiskt exempel för förklaring, inte ett verkligt testresultat. Föreställ dig en liten butikskomponent som hämtar produkter efter att komponenten först visas. Utvecklaren skriver:

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

Vid den första renderingen är products undefined eftersom inget initialvärde skickades till useState. Reacts dokumentation för useState anger att state-värdet vid den första renderingen motsvarar det initiala tillstånd du tillhandahåller. Hämtningen körs efteråt, så renderingen kan nå products.map(...) innan svaret anländer. React useState-referens.

AI-genererad illustration av webbläsarkonsolen som visar Cannot read properties of undefined reading map i en React-komponent.
AI-genererad illustration av JavaScript-felet som pekar på en listrendering som anropar .map() på ett odefinierat värde.

Steg 1: Hitta exakt vilket värde som är odefinierat

Börja vid stackspåret och hitta raden som innehåller .map(). I den illustrativa komponenten är den raden products.map(...), så products är det första värdet att inspektera. I en större komponent kan det misslyckade uttrycket istället vara data.items.map(), props.users.map() eller response.results.map().

Använd webbläsarens felsökare eller en tillfällig loggning omedelbart innan renderingslogiken:

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

Detta skiljer på flera buggar som ser likadana ut i UI:t. Om värdet är undefined, undersök initiering eller en saknad egenskap. Om det är null, kan din laddnings-/datamodell uttryckligen använda null. Om det är ett objekt, läser du kanske fel nivå av ett API-svar. Om det är en sträng eller ett nummer, skiljer sig uppströms datakontrakt från vad komponenten förväntar sig.

Ersätt inte automatiskt varje misslyckat uttryck med valfri kedjning (optional chaining) innan du förstår värdet. Det kan undertrycka kraschen men lämna felaktigt dataflöde kvar.

Steg 2: Initiera collectionsstate som en collection när det stämmer med din modell

För den hypotetiska produktlistan är en tom array ett rimligt initialtillstånd eftersom “inga produkter har laddats än” säkert kan representeras som en samling med noll objekt:

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

Nu kan den första renderingen köra products.map(...) eftersom en tom array har en map-metod. När begäran senare uppdaterar state:n, renderar React igen med de returnerade produkterna.

AI-genererad illustration av en React useState-deklaration initierad med en tom array.
AI-genererad illustration av att initiera liststate med useState([]) så att den första renderingen har en array.

Detta är en stark lösning när state:n konceptuellt alltid är en array. Det är mindre lämpligt när undefined eller null bär på meningsfull information, som “inte begärd än”, medan [] betyder “begäran är klar och det finns noll resultat”. I det fallet, håll tillstånden distinkta och rendera laddnings-, fel- och tomma tillstånd explicit.

Steg 3: Verifiera API-svarets struktur innan du lägger det i state

Initiering löser bara den första renderingen. Den skyddar inte komponenten om servern till slut returnerar en annan struktur. Antag att API:t faktiskt returnerar:

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

Då lagrar setProducts(data) ett objekt, inte en array. Det troliga felet ändras till något som products.map is not a function. Den korrekta tilldelningen skulle vara setProducts(data.products), förutsatt att den egenskapen garanterat är en array.

För data som korsar en extern gräns, validera den:

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-genererad illustration av en React-komponent som kontrollerar Array.isArray innan den anropar map.
AI-genererad illustration av att skydda en listrendering med Array.isArray() innan .map() används.

Detta är viktigt eftersom en “säker standard” inte ska förvandla felaktig produktionsdata till en tyst tom sida. Om en array krävs av kontraktet, kan loggning eller att synliggöra ett fel vara mer användbart än att konvertera varje oväntat svar till [].

Steg 4: Välj rätt renderingskontroll för data som legitimt kan saknas

React stöder vanlig JavaScript-villkorlig rendering. De officiella dokumenten visar användning av if, ternära uttryck och && för att bestämma vilken JSX som ska returneras. React guide för villkorlig rendering.

För den hypotetiska produktsidan är ett explicit flöde för laddning och fel ofta det tydligaste:

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

Valfri kedjning är också giltig när “saknas just nu” helt enkelt ska producera inget mappat resultat:

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

MDN förklarar att valfri kedjning (?.) avbryts (short-circuits) när värdet till vänster om den är null eller undefined istället för att kasta ett TypeError. MDN referens för valfri kedjning.

AI-genererad illustration av valfri kedjning använd före map i en React-komponent.
AI-genererad illustration av valfri kedjning med users?.map(...) för data som tillfälligt kan vara odefinierad.

Begränsningen är viktig: products?.map(...) förhindrar detta specifika nullish-access-fel, men det bevisar inte att products är en array. Om products blir ett objekt, löses products?.map fortfarande till en odefinierad egenskap och att försöka anropa den kan misslyckas. Använd schemavalidering eller Array.isArray() när datatypen i sig är osäker.

Vilken lösning bör du välja?

SituationBästa första dragVarför
State bör alltid vara en listauseState([])Ger den första renderingen rätt datatyp.
Saknad data har ett meningsfullt laddningstillståndVillkorlig renderingHåller “inte laddad” separat från “laddad men tom”.
API-strukturen kan variera eller vara felaktigValidera med Array.isArray() eller ett schemaFörhindrar att dålig extern data kommer in i komponentstate utan att upptäckas.
Prop är valfri per designValfri kedjning eller ett standardprop-värdeUndviker att dereferera ett legitimt frånvarande värde.
Fel uppstår efter en refactorKontrollera egenskaps- och propnamnEtt omdöpt fält kan göra att en tidigare giltig array blir undefined.

Vanliga fall som ser ut som samma fel

API:t returnerar { items: [...] }, men komponenten förväntar sig en array

Inspektera nätverkssvaret och tilldela arrayegenskapen istället för wrapperobjektet. Gissa inte strukturen från ett gammalt exempel eller TypeScript-gränssnitt om det levande svaret skiljer sig.

En föräldrakomponent glömmer att skicka propen

Detta kommer att misslyckas:

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

// Parent accidentally omits users:
<UserList />

Om en utelämnad prop ska betyda en tom lista, gör ett standardvärde det kontraktet explicit:

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

En nästlad egenskap saknas

Med response.data.items.map(...) kan varje saknad mellanliggande egenskap misslyckas. Valfri kedjning som response?.data?.items är användbar för att läsa osäkra nästlade värden, men validera den slutliga samlingen innan du behandlar den som en array.

Den första renderingen sker innan en fetch Effect är klar

React Effects körs efter rendering. Reacts dokumentation noterar också att manuell hämtning av data inuti Effects är vanligt i klientapplikationer men kan ha nackdelar som vattenfall, saknad serverrenderad data och manuellt arbete med cachning/tävlingsvillkor. Om du använder ett React-ramverk, kan dess inbyggda mekanism för datainläsning vara ett bättre arkitektoniskt val. React useEffect-referens.

En säkrare slutversion av den illustrativa komponenten

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

Denna version skiljer avsiktligt på “inte laddad”, “misslyckad”, “tom” och “har data”. Det är mer omfattande än ett enda valfri-kedjeuttryck, men det ger användaren ett meningsfullt UI för varje tillstånd och gör ett felaktigt API-svar synligt under felsökning.

Snabb checklista innan du anser att buggen är åtgärdad

  • Identifiera det exakta värdet omedelbart före .map().
  • Bekräfta dess värde och typ vid den rendering som misslyckas.
  • Initiera liststate med [] när en tom array korrekt representerar initialtillståndet.
  • Kontrollera om API:t returnerar en array direkt eller omsluter den i ett objekt.
  • Validera extern data innan du lagrar den i state när kontraktet är viktigt.
  • Använd ett laddningstillstånd om undefined betyder “inte laddad än”.
  • Använd valfri kedjning när frånvaro är legitim, inte som en ersättning för att förstå dålig data.
  • Kontrollera omdöpta eller utelämnade props efter refactors.
  • Ge renderade listobjekt stabila nycklar från datan, enligt rekommendationen i Reacts dokumentation för listrendering.

För den hypotetiska produktlistan var grundorsaken att den första renderingen fick undefined där komponenten omedelbart förväntade sig en array. I en verklig applikation kan samma felmeddelande komma från state-initiering, props, nästlade egenskaper eller API-data. Åtgärda datakontraktet först, välj sedan en renderingskontroll som korrekt representerar vad “saknas” betyder i ditt UI.

Lämna en kommentar

Hur man åtgärdar "Tailwind CSS-stilar uppdateras inte" i en Vite React-app

Hur man åtgärdar "Tailwind CSS-stilar uppdateras inte" i en Vite React-app

Åtgärda Tailwind CSS-stilar som inte uppdateras i Vite React genom att kontrollera Tailwind v4-inställningar, CSS-importer, källkodsidentifiering, dynamiska klasser, HMR och inaktuella cacher.

Så här åtgärdar du ModuleNotFoundError: Ingen modul med namnet 'pip' i Python 3

Så här åtgärdar du ModuleNotFoundError: Ingen modul med namnet 'pip' i Python 3

Åtgärda Python 3:s ModuleNotFoundError för pip på Windows, macOS och Linux med ensurepip, OS-paket, virtuella miljöer och tolkkontroller.

Hur man åtgärdar "Tillstånd nekad (publickey)" i GitHub SSH

Hur man åtgärdar "Tillstånd nekad (publickey)" i GitHub SSH

Åtgärda GitHub SSH-behörighet nekad (publickey) genom att kontrollera värden, aktiv SSH-nyckel, GitHub-konto, SSO-auktorisering, fjärr-URL och port 22-åtkomst.

Hur man åtgärdar "Git Push Rejected: Non-Spolar framåt" utan att förlora ändringar

Hur man åtgärdar "Git Push Rejected: Non-Spolar framåt" utan att förlora ändringar

Åtgärda en Git-push som inte snabbspolar framåt på ett säkert sätt. Skydda lokalt arbete, hämta fjärrcommits, välj merge eller rebase, lös konflikter och pusha utan att förlora ändringar.

Hur man åtgärdar "Nginx 502 Bad Gateway" vid proxyanvändning till Node.js

Hur man åtgärdar "Nginx 502 Bad Gateway" vid proxyanvändning till Node.js

Åtgärda Nginx 502 Bad Gateway-fel med en Node.js-uppström genom att kontrollera appporten, NGINX-loggarna, proxy_pass-adressen, containernätverk, timeouts och omladdning.

How to Fix “Type 'null' Is Not Assignable to Type” in TypeScript

How to Fix “Type 'null' Is Not Assignable to Type” in TypeScript

Fix TypeScript's “Type 'null' is not assignable to type” error with union types, narrowing, defaults, and safe assertions under strictNullChecks.

Så här åtgärdar du felet ”Prisma Client has not been generated yet”

Så här åtgärdar du felet ”Prisma Client has not been generated yet”

Åtgärda felet att Prisma Client inte har genererats genom att kontrollera din generator, ditt schema, utdatasökvägen, importerna, versionerna, monorepo-konfigurationen och byggstegen vid distribution.

Hur man åtgärdar "ERR_MODULE_NOT_FOUND" i Node.js ESM-importer

Hur man åtgärdar "ERR_MODULE_NOT_FOUND" i Node.js ESM-importer

Åtgärda Node.js ERR_MODULE_NOT_FOUND i ESM genom att kontrollera importsökvägar, filtillägg, paketinstallation, exporter, ESM-läge och rena installationer.

Så här åtgärdar du SSL-certifikatproblemet: Unable to Get Local Issuer Certificate i Git

Så här åtgärdar du SSL-certifikatproblemet: Unable to Get Local Issuer Certificate i Git

Åtgärda Gits fel 'unable to get local issuer certificate' genom att identifiera förtroendebakgrunden, installera rätt CA-kedja och hålla SSL-verifieringen aktiverad.

Så åtgärdar du MongoDB-nätverksavbrott vid Mongoose-anslutning

Så åtgärdar du MongoDB-nätverksavbrott vid Mongoose-anslutning

Åtgärda MongoDB-nätverksavbrott i Mongoose genom att identifiera avbrottstypen, testa Atlas- eller TCP-anslutning, korrigera URI:n och justera tidsgränser endast när det är motiverat.