TypeError: Cannot read properties of undefined (reading 'map') even though useState() is initialized with array
TypeError: Cannot read properties of undefined (reading 'map') even though useState() is initialized with array
我遇到“TypeError:无法读取未定义的属性(读取 'map')”,即使 useState() 是用数组 初始化的。该错误仅发生在一个组件中。其他组件,我认为,也以相同的方式使用 useState 和 useEffect,不会解决此错误。
import { useState, useEffect } from "react/cjs/react.development";
import * as constants from "../../../../constants";
export default function Keywords(props) {
const [movieKeywords, setMovieKeywords] = useState([]);
useEffect(() => {
const fetchKeywords = async () => {
const data = await fetch(
`${constants.TMDB_BASE_PATH}movie/${props.id}/keywords?api_key=${constants.API_KEY}`
);
const jsonData = await data.json();
setMovieKeywords(jsonData.keywords);
console.log("xdd");
};
fetchKeywords();
}, []);
return (
<div className="flex flex-wrap">
{movieKeywords.map((keyword) => {
return (
<div className="border font-oxygen m-1 rounded-xl cursor-pointer text-xs text-gray-300 px-2 py-1">
<p>{keyword.name}</p>
</div>
);
})}
</div>
);
}
如果有人能指出正确的方向,我将很高兴。
在 API 调用和渲染的时间上,您可能只差了几毫秒。一个好的做法是在尝试渲染任何 JSX 之前检查您正在映射的数组是否存在。将您的初始状态设置为 null 并在您的地图行上执行 optional chaining。
像这样重构你的组件:
import { useState, useEffect } from "react/cjs/react.development";
import * as constants from "../../../../constants";
export default function Keywords(props) {
const [movieKeywords, setMovieKeywords] = useState();
useEffect(() => {
const fetchKeywords = async () => {
const data = await fetch(
`${constants.TMDB_BASE_PATH}movie/${props.id}/keywords?api_key=${constants.API_KEY}`
);
const jsonData = await data.json();
setMovieKeywords(jsonData.keywords);
console.log("xdd");
};
fetchKeywords();
}, []);
return (
<div className="flex flex-wrap">
{movieKeywords?.map((keyword) => {
return (
<div className="border font-oxygen m-1 rounded-xl cursor-pointer text-xs text-gray-300 px-2 py-1">
<p>{keyword.name}</p>
</div>
);
})}
</div>
);
}
注意 movieKeywords?.map
,在 movieKeywords
不为 null 之前不会执行映射,这意味着它将等到提取解决并且您的状态已设置。
"jsonData.keywords 不是未定义的。" - 该错误实际上是在通知您确实如此。 setMovieKeywords(jsonData.keywords);
更新状态然后 movieKeywords
未定义且无法访问 .map
property/method.
据我所知,您缺少 props.id
作为 useEffect
和 fetch
的依赖项。听起来 props.id
最初不是 API 请求的有效值,您收到未定义的 keywords
响应。
如果您拥有所有必需的参数,您应该只发出 API 请求,并且您的代码应该足够健壮以处理可能无效和错误的响应。
- 将
props.id
添加到 useEffect
挂钩的依赖项数组。
- 仅在
id
为真时才发出 fetch
请求。
- 处理来自
fetch
的可能被拒绝的 Promise。
- 处理任何具有未定义值的潜在不良状态更新。
示例:
import { useState, useEffect } from "react/cjs/react.development";
import * as constants from "../../../../constants";
export default function Keywords({ id }) {
const [movieKeywords, setMovieKeywords] = useState([]);
useEffect(() => {
const fetchKeywords = async (id) => {
try { // <-- (3) use try/catch to handle rejected Promise or other exceptions
const data = await fetch(
`${constants.TMDB_BASE_PATH}movie/${id}/keywords?api_key=${constants.API_KEY}`
);
const jsonData = await data.json();
if (jsonData) { // <-- (4) only update state if defined response value
setMovieKeywords(jsonData.keywords);
}
} catch(error) {
// handle any errors, log, set error state, ignore(?), etc...
}
console.log("xdd");
};
if (id) { // <-- (2) only fetch if `id` is truthy
fetchKeywords(id);
}
}, [id]); // <-- (1) add `id` as dependency
return (
<div className="flex flex-wrap">
{movieKeywords?.map((keyword) => { // <-- Use Optional Chaining in case `movieKeywords` becomes falsey for any reason
return (
<div className="border font-oxygen m-1 rounded-xl cursor-pointer text-xs text-gray-300 px-2 py-1">
<p>{keyword.name}</p>
</div>
);
})}
</div>
);
}
我遇到“TypeError:无法读取未定义的属性(读取 'map')”,即使 useState() 是用数组 初始化的。该错误仅发生在一个组件中。其他组件,我认为,也以相同的方式使用 useState 和 useEffect,不会解决此错误。
import { useState, useEffect } from "react/cjs/react.development";
import * as constants from "../../../../constants";
export default function Keywords(props) {
const [movieKeywords, setMovieKeywords] = useState([]);
useEffect(() => {
const fetchKeywords = async () => {
const data = await fetch(
`${constants.TMDB_BASE_PATH}movie/${props.id}/keywords?api_key=${constants.API_KEY}`
);
const jsonData = await data.json();
setMovieKeywords(jsonData.keywords);
console.log("xdd");
};
fetchKeywords();
}, []);
return (
<div className="flex flex-wrap">
{movieKeywords.map((keyword) => {
return (
<div className="border font-oxygen m-1 rounded-xl cursor-pointer text-xs text-gray-300 px-2 py-1">
<p>{keyword.name}</p>
</div>
);
})}
</div>
);
}
如果有人能指出正确的方向,我将很高兴。
在 API 调用和渲染的时间上,您可能只差了几毫秒。一个好的做法是在尝试渲染任何 JSX 之前检查您正在映射的数组是否存在。将您的初始状态设置为 null 并在您的地图行上执行 optional chaining。
像这样重构你的组件:
import { useState, useEffect } from "react/cjs/react.development";
import * as constants from "../../../../constants";
export default function Keywords(props) {
const [movieKeywords, setMovieKeywords] = useState();
useEffect(() => {
const fetchKeywords = async () => {
const data = await fetch(
`${constants.TMDB_BASE_PATH}movie/${props.id}/keywords?api_key=${constants.API_KEY}`
);
const jsonData = await data.json();
setMovieKeywords(jsonData.keywords);
console.log("xdd");
};
fetchKeywords();
}, []);
return (
<div className="flex flex-wrap">
{movieKeywords?.map((keyword) => {
return (
<div className="border font-oxygen m-1 rounded-xl cursor-pointer text-xs text-gray-300 px-2 py-1">
<p>{keyword.name}</p>
</div>
);
})}
</div>
);
}
注意 movieKeywords?.map
,在 movieKeywords
不为 null 之前不会执行映射,这意味着它将等到提取解决并且您的状态已设置。
"jsonData.keywords 不是未定义的。" - 该错误实际上是在通知您确实如此。 setMovieKeywords(jsonData.keywords);
更新状态然后 movieKeywords
未定义且无法访问 .map
property/method.
据我所知,您缺少 props.id
作为 useEffect
和 fetch
的依赖项。听起来 props.id
最初不是 API 请求的有效值,您收到未定义的 keywords
响应。
如果您拥有所有必需的参数,您应该只发出 API 请求,并且您的代码应该足够健壮以处理可能无效和错误的响应。
- 将
props.id
添加到useEffect
挂钩的依赖项数组。 - 仅在
id
为真时才发出fetch
请求。 - 处理来自
fetch
的可能被拒绝的 Promise。 - 处理任何具有未定义值的潜在不良状态更新。
示例:
import { useState, useEffect } from "react/cjs/react.development";
import * as constants from "../../../../constants";
export default function Keywords({ id }) {
const [movieKeywords, setMovieKeywords] = useState([]);
useEffect(() => {
const fetchKeywords = async (id) => {
try { // <-- (3) use try/catch to handle rejected Promise or other exceptions
const data = await fetch(
`${constants.TMDB_BASE_PATH}movie/${id}/keywords?api_key=${constants.API_KEY}`
);
const jsonData = await data.json();
if (jsonData) { // <-- (4) only update state if defined response value
setMovieKeywords(jsonData.keywords);
}
} catch(error) {
// handle any errors, log, set error state, ignore(?), etc...
}
console.log("xdd");
};
if (id) { // <-- (2) only fetch if `id` is truthy
fetchKeywords(id);
}
}, [id]); // <-- (1) add `id` as dependency
return (
<div className="flex flex-wrap">
{movieKeywords?.map((keyword) => { // <-- Use Optional Chaining in case `movieKeywords` becomes falsey for any reason
return (
<div className="border font-oxygen m-1 rounded-xl cursor-pointer text-xs text-gray-300 px-2 py-1">
<p>{keyword.name}</p>
</div>
);
})}
</div>
);
}