TypeError:即使 useState() 已使用数组初始化,也无法读取未定义的属性(读取“map”)
2022-03-04
27804
我得到了“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>
);
}
如果有人能给我指明正确的方向,我将非常高兴。
2个回答
API 调用和渲染的时间可能只差几毫秒。一个好的做法是在尝试渲染任何 JSX 之前检查要映射的数组是否存在。将初始状态设置为 null,然后在映射行上执行 可选链接 。
像这样重构您的组件:
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,这意味着它将等到提取解析并设置您的状态。
PsiKai
2022-03-04
“jsonData.keywords 并非未定义。” - 但该错误实际上是在通知您它已未定义。
setMovieKeywords(jsonData.keywords);
更新状态,然后
movieKeywords
未定义,并且无法访问
.map
属性/方法。
据我所知,您缺少
props.id
作为
useEffect
和
fetch
的依赖项。听起来
props.id
最初不是 API 请求的有效值,并且您收到未定义的
keywords
响应。
只有在您拥有所有必需参数的情况下才应发出 API 请求,并且您的代码应该足够强大,能够处理潜在的无效和不良响应。
-
将
props.id
添加到useEffect
钩子的依赖项数组。 -
仅当
id
为真时才发出fetch
请求。 -
处理可能被拒绝的
fetch
中的 Promises。 - 处理任何具有未定义值的潜在不良状态更新。
示例:
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>
);
}
Drew Reese
2022-03-04