使用React.js和Axios调用POKEAPI时无法获取Pokemon的flavor_text
问题:无法从PokeAPI获取宝可梦的flavor_text描述信息
我正在用PokeAPI练手API处理,现在要拿每只宝可梦的flavor_text(也就是描述信息),试了好多次都没成功。妙蛙种子的物种数据接口返回的JSON里,flavor_text_entries就是存放描述的字段,但我的代码里,获取habitat的逻辑能正常跑,处理flavor_text的map部分却出问题,打印descriptions或者descriptions[0]都没结果。
我的useEffect代码如下:
export default function Card({ pokemon }, { key }) { const src = url + `${pokemon.id}` + ".png"; const [habitat, setHabitat] = useState(null); const [descriptions, setDescriptions] = useState([]); useEffect(() => { const controller = new AbortController(); axios .get(url2 + `${pokemon.name}`, { signal: controller.signal }) .then((res) => setHabitat(res.data.habitat.name)) .then((res) => setDescriptions( res.data.flavor_text_entries.map((ob) => ob.flavor_text) ) ) .catch((err) => { if (axios.isCancel(err)) { } else { console.log("warning your useEffect is behaving"); } }); return () => { // cancel the request before component unmounts controller.abort(); }; }, [pokemon]); }
问题原因
你这里的Promise链式调用写错了:第一个then里只调用了setHabitat,没有返回任何值,所以第二个then接收的res是undefined,自然找不到res.data.flavor_text_entries,也就没法生成描述数组。
修复方案
有两种简单的修复方式:
方式一:合并状态更新到同一个then里
直接在同一个then里处理两个状态的更新,复用同一个请求返回的res对象:
useEffect(() => { const controller = new AbortController(); axios .get(url2 + `${pokemon.name}`, { signal: controller.signal }) .then((res) => { setHabitat(res.data.habitat.name); // 处理flavor_text_entries生成描述数组 const flavorTexts = res.data.flavor_text_entries.map(ob => ob.flavor_text); setDescriptions(flavorTexts); }) .catch((err) => { if (!axios.isCancel(err)) { console.log("请求出错:", err); } }); return () => controller.abort(); }, [pokemon]);
方式二:在第一个then里返回res
如果非要分开写两个then,记得在第一个then里把res返回,让第二个then能拿到数据:
useEffect(() => { const controller = new AbortController(); axios .get(url2 + `${pokemon.name}`, { signal: controller.signal }) .then((res) => { setHabitat(res.data.habitat.name); return res; // 关键:把res传递给下一个then }) .then((res) => { const flavorTexts = res.data.flavor_text_entries.map(ob => ob.flavor_text); setDescriptions(flavorTexts); }) .catch((err) => { if (!axios.isCancel(err)) { console.log("请求出错:", err); } }); return () => controller.abort(); }, [pokemon]);
另外,你还可以根据需求过滤描述的语言(比如只保留中文),因为flavor_text_entries里包含多语言描述:
const flavorTexts = res.data.flavor_text_entries .filter(entry => entry.language.name === 'zh-Hans') // 筛选简体中文描述 .map(ob => ob.flavor_text);
内容的提问来源于stack exchange,提问作者AConcernedJunior
相关产品推荐
相关产品推荐

