如何修復React報錯 – TypeError: Cannot Read Property ‘Map’ of Undefined

如何修復React報錯 - TypeError: Cannot Read Property ‘Map’ of Undefined

您是否在 React 應用程式中遇到了令人沮喪的 “TypeError: Cannot Read Property ‘Map’ of Undefined” 錯誤?這種錯誤的除錯可能很棘手,不過不用擔心,我們會幫你解決。

在本文中,我們將向您介紹常見的原因和解決方案,以幫助您修復此錯誤。無論您是經驗豐富的 React 開發人員,還是剛剛起步,本指南都將幫助您的應用程式重回正軌。

什麼原因導致 “TypeError: Cannot Read Property ‘Map’ of Undefined” 錯誤?

TypeError: Cannot Read Property ‘Map’ of Undefined 錯誤通常發生在您嘗試訪問 React 程式碼中未定義值的屬性或方法時。

通俗地說,當您嘗試對映未定義的值時就會發生該錯誤,例如尚未初始化或尚未接收資料的陣列。

在下面的示例中,您正在從 JSON 佔位符資料中獲取待辦事項,但在來自 API 請求的資料到達之前,map 方法就已被呼叫。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
import { useState, useEffect } from 'react';
function App() {
const [todos, setTodos] = useState();
useEffect(() => {
const getTodos = async () => {
const response = await fetch(
'https://jsonplaceholder.typicode.com/todos?_limit=5'
);
const data = await response.json();
setTodos(data);
};
getTodos();
}, []);
console.log(todos);
return (
<div>
{todos.map((todo) => (
<div key={todo.id}>
<h2>Item: {todo.title}</h2>
</div>
))}
</div>
);
}
export default App;
import { useState, useEffect } from 'react'; function App() { const [todos, setTodos] = useState(); useEffect(() => { const getTodos = async () => { const response = await fetch( 'https://jsonplaceholder.typicode.com/todos?_limit=5' ); const data = await response.json(); setTodos(data); }; getTodos(); }, []); console.log(todos); return ( <div> {todos.map((todo) => ( <div key={todo.id}> <h2>Item: {todo.title}</h2> </div> ))} </div> ); } export default App;
import { useState, useEffect } from 'react';
function App() {
const [todos, setTodos] = useState();
useEffect(() => {
const getTodos = async () => {
const response = await fetch(
'https://jsonplaceholder.typicode.com/todos?_limit=5'
);
const data = await response.json();
setTodos(data);
};
getTodos();
}, []);
console.log(todos);
return (
<div>
{todos.map((todo) => (
<div key={todo.id}>
<h2>Item: {todo.title}</h2>
</div>
))}
</div>
);
}
export default App;

上面的程式碼會產生 “TypeError: Cannot read properties of undefined (reading ‘map’)” 錯誤:

 "TypeError: Cannot read properties of undefined (reading 'map')" 錯誤

TypeError: Cannot read properties of undefined (reading ‘map’) 錯誤資訊

您需要尋找一種方法,讓 React 在陣列填充之前就知道 todos 狀態是一個陣列,或者在 todos 狀態變數從 API 請求中獲取資料之前避免執行 map 方法。

修復 “TypeError:無法讀取未定義的屬性’Map'” 錯誤

以下是修復 React 中“TypeError: Cannot Read Property ‘Map’  of Undefined”錯誤:

  1. 將狀態變數初始化為空陣列
  2. 使用比較運算子
  3. 使用可選的鏈式運算子 (?.)

讓我們逐一探討這些解決方案,以及它們如何幫助您解決 React 程式碼中的錯誤。

1. 將狀態變數初始化為空陣列

解決 “TypeError: Cannot Read Property ‘Map’ of Undefined”(無法讀取未定義的屬性 “Map”)錯誤的直接解決方案之一是確保你試圖對映的陣列變數是已定義的。

你可以將狀態變數初始化為預設的空陣列,這將確保變數始終存在,並且在你嘗試對映它時不會出錯。

例如,下面是兩個類似的元件,第一個元件的狀態變數沒有初始化為空陣列,而第二個元件的狀態變數初始化為空陣列:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// Before initializing your state variable to an empty array
function MyComponent() {
const [myList, setMyList] = useState();
return (
<ul>
{myList.map(item => <li>{item}</li>)}
</ul>
);
}
// After initializing your state variable to an empty array
function MyComponent() {
const [myList, setMyList] = useState([]);
return (
<ul>
{myList.map(item => <li>{item}</li>)}
</ul>
);
}
// Before initializing your state variable to an empty array function MyComponent() { const [myList, setMyList] = useState(); return ( <ul> {myList.map(item => <li>{item}</li>)} </ul> ); } // After initializing your state variable to an empty array function MyComponent() { const [myList, setMyList] = useState([]); return ( <ul> {myList.map(item => <li>{item}</li>)} </ul> ); }
// Before initializing your state variable to an empty array
function MyComponent() {
const [myList, setMyList] = useState();
return (
<ul>
{myList.map(item => <li>{item}</li>)}
</ul>
);
}
// After initializing your state variable to an empty array
function MyComponent() {
const [myList, setMyList] = useState([]);
return (
<ul>
{myList.map(item => <li>{item}</li>)}
</ul>
);
}

在上面的示例中,預設情況下使用 useState([])myList 狀態變數初始化為空陣列。這確保了即使 myList 最初未定義,它也始終是一個陣列,而不會引發 “TypeError: Cannot Read Property ‘Map’ of Undefined” 錯誤。

在獲取示例中,也可以將 todos 狀態變數初始化為空陣列( [] ):

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
import { useState, useEffect } from 'react';
function App() {
// Initialize the state to an empty array of todos.
const [todos, setTodos] = useState([]);
useEffect(() => {
const getTodos = async () => {
const response = await fetch(
'https://jsonplaceholder.typicode.com/todos?_limit=5'
);
const data = await response.json();
setTodos(data);
};
getTodos();
}, []);
console.log(todos);
return (
<div>
{todos.map((todo) => (
<div key={todo.id}>
<h2>Item: {todo.title}</h2>
</div>
))}
</div>
);
}
export default App;
import { useState, useEffect } from 'react'; function App() { // Initialize the state to an empty array of todos. const [todos, setTodos] = useState([]); useEffect(() => { const getTodos = async () => { const response = await fetch( 'https://jsonplaceholder.typicode.com/todos?_limit=5' ); const data = await response.json(); setTodos(data); }; getTodos(); }, []); console.log(todos); return ( <div> {todos.map((todo) => ( <div key={todo.id}> <h2>Item: {todo.title}</h2> </div> ))} </div> ); } export default App;
import { useState, useEffect } from 'react';
function App() {
// Initialize the state to an empty array of todos.
const [todos, setTodos] = useState([]);
useEffect(() => {
const getTodos = async () => {
const response = await fetch(
'https://jsonplaceholder.typicode.com/todos?_limit=5'
);
const data = await response.json();
setTodos(data);
};
getTodos();
}, []);
console.log(todos);
return (
<div>
{todos.map((todo) => (
<div key={todo.id}>
<h2>Item: {todo.title}</h2>
</div>
))}
</div>
);
}
export default App;

2. 使用比較運算子

另一種解決方案是在對映陣列變數之前,使用比較運算子檢查陣列變數是否已定義。您可以使用三元或邏輯 AND (&&) 運算子來實現這一目的。

下面是使用三元運算子的示例:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
function MyComponent() {
const [myList, setMyList] = useState();
return (
<ul>
{myList ? myList.map(item => <li>{item}</li>) : null}
</ul>
);
}
function MyComponent() { const [myList, setMyList] = useState(); return ( <ul> {myList ? myList.map(item => <li>{item}</li>) : null} </ul> ); }
function MyComponent() {
const [myList, setMyList] = useState();
return (
<ul>
{myList ? myList.map(item => <li>{item}</li>) : null}
</ul>
);
}

在此示例中,在嘗試對映 myList 之前,要檢查是否定義了 myList 陣列變數。如果 myList 未定義,三元運算子將返回 null,並且不會呈現任何內容。如果 myList 已定義,則呼叫 map 函式,並渲染列表項。

這與使用邏輯 AND 運算子類似:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
function MyComponent() {
const [myList, setMyList] = useState();
return (
<ul>
{myList && myList.map(item => <li>{item}</li>)}
</ul>
);
}
function MyComponent() { const [myList, setMyList] = useState(); return ( <ul> {myList && myList.map(item => <li>{item}</li>)} </ul> ); }
function MyComponent() {
const [myList, setMyList] = useState();
return (
<ul>
{myList && myList.map(item => <li>{item}</li>)}
</ul>
);
}

通過使用三元運算子等比較運算子,您可以處理載入問題,這樣,當您從應用程式介面匯入資料時,螢幕上就會顯示其他內容:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
import { useState, useEffect } from 'react';
function App() {
const [todos, setTodos] = useState();
useEffect(() => {
const getTodos = async () => {
const response = await fetch(
'https://jsonplaceholder.typicode.com/todos?_limit=5'
);
const data = await response.json();
setTodos(data);
};
getTodos();
}, []);
console.log(todos);
return (
<div>
{todos ? (
todos.map((todo) => (
<div key={todo.id}>
<h2>Item: {todo.title}</h2>
</div>
))
) : (
<h1>Loading...</h1>
)}
</div>
);
}
export default App;
import { useState, useEffect } from 'react'; function App() { const [todos, setTodos] = useState(); useEffect(() => { const getTodos = async () => { const response = await fetch( 'https://jsonplaceholder.typicode.com/todos?_limit=5' ); const data = await response.json(); setTodos(data); }; getTodos(); }, []); console.log(todos); return ( <div> {todos ? ( todos.map((todo) => ( <div key={todo.id}> <h2>Item: {todo.title}</h2> </div> )) ) : ( <h1>Loading...</h1> )} </div> ); } export default App;
import { useState, useEffect } from 'react';
function App() {
const [todos, setTodos] = useState();
useEffect(() => {
const getTodos = async () => {
const response = await fetch(
'https://jsonplaceholder.typicode.com/todos?_limit=5'
);
const data = await response.json();
setTodos(data);
};
getTodos();
}, []);
console.log(todos);
return (
<div>
{todos ? (
todos.map((todo) => (
<div key={todo.id}>
<h2>Item: {todo.title}</h2>
</div>
))
) : (
<h1>Loading...</h1>
)}
</div>
);
}
export default App;

3. 使用可選的鏈式運算子 (?.)

您還可以使用 ES2020 中引入的可選鏈式運算子 (?.) 。該運算子允許您安全地訪問屬性或方法,例如陣列的 map 方法,而不會在陣列未定義時產生錯誤。

下面是一個使用鏈式運算子檢查 myList 狀態變數的功能元件示例:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
function MyComponent() {
const [myList, setMyList] = useState();
return (
<div>
{myList?.map((item) => (
<p>{item}</p>
))}
</div>
);
}
function MyComponent() { const [myList, setMyList] = useState(); return ( <div> {myList?.map((item) => ( <p>{item}</p> ))} </div> ); }
function MyComponent() {
const [myList, setMyList] = useState();
return (
<div>
{myList?.map((item) => (
<p>{item}</p>
))}
</div>
);
}

在上面的示例中,我們使用了可選的鏈式運算子來安全地訪問 myList 陣列變數。如果 myList 未定義,則不會呈現任何內容。如果 myList 已定義,則將呼叫 map 方法,並渲染列表項。

小結

在 React 中對未定義或空值使用 map 方法時,可能會出現 “TypeError: Cannot Read Property ‘Map’ of Undefined” 錯誤。

為修復此錯誤,我們討論了三種解決方案。不過,使用比較運算子是最通用的解決方案,因為它可以處理 API 可能傳送空響應或空值的情況。

此外,在不確定接收到的資料是否為陣列時,可以新增一些方法,在呼叫 map 方法之前檢查並轉換資料型別。

現在輪到你了: 您遇到過這個問題嗎?你是如何解決的?您還使用了本文未涉及的其他方法嗎?請在評論中告訴我們!

評論留言