React重渲染时PokeAPI返回对象为null的问题求助
问题解决:重渲染后PokeAPI属性访问报错
核心问题分析
重渲染时出现response.name报错,本质是未处理response为null/undefined的边界情况,同时useAxios的请求参数格式有误,可能导致请求重试时response未及时更新或请求失败。
具体修复步骤
1. 给Pokecard组件添加空值保护
在访问response的嵌套属性时,使用可选链操作符?.避免空值访问错误,同时可结合条件渲染控制组件渲染时机:
// 修改后的Pokecard组件 import { EditOutlined, EllipsisOutlined, SettingOutlined, } from "@ant-design/icons"; import { Avatar, Card, Col, Row } from "antd"; function Pokecard(values: any) { const { response} = values; const { Meta } = Card; // 当response为空时,显示占位内容 if (!response) return <div>暂无数据</div>; return ( <Row gutter={[10, 10]}> <Col> <Card style={{ width: 300 }} cover={ <img alt="宝可梦图片" src={response.sprites?.front_default} /> } actions={[ <SettingOutlined key="setting" />, <EditOutlined key="edit" />, <EllipsisOutlined key="ellipsis" />, ]} > <Meta avatar={<Avatar src="https://joeschmoe.io/api/v1/random" />} title={response.name} description="" /> </Card> </Col> </Row> ); } export default Pokecard;
2. 修复useAxios的请求参数与状态管理
get请求的参数格式与post等请求不同,需区分处理;同时在请求开始时重置loading状态,避免状态混乱:
// 修改后的useAxios插件 import axios from "axios"; import Request from "../interfaces/request"; import { useState, useEffect } from "react"; enum Methods { get = "get", post = "post", default = "get", } const useAxios = ({ url, method = Methods.default, body = "{}", headers = "{}" }: Request) => { axios.defaults.baseURL = "https://pokeapi.co/api/v2/pokemon"; const [response, setResponse] = useState<null | any>(null); const [error, setError] = useState(""); const [loading, setLoading] = useState(true); const fetchData = () => { setLoading(true); // 请求开始时重置loading状态 const parsedHeaders = JSON.parse(headers); const parsedBody = JSON.parse(body); try { if (method === Methods.get) { // get请求:url + 配置参数 axios.get(url, { headers: parsedHeaders }) .then(res => setResponse(res.data)) .catch(err => setError(err.message || "请求失败")) .finally(() => setLoading(false)); } else { // post/put等请求:url + 请求体 + 配置参数 axios[method](url, parsedBody, { headers: parsedHeaders }) .then(res => setResponse(res.data)) .catch(err => setError(err.message || "请求失败")) .finally(() => setLoading(false)); } } catch (err) { setError("请求参数解析失败"); setLoading(false); } }; useEffect(() => { fetchData(); }, [method, url, body, headers]); return { response, error, loading }; }; export default useAxios;
3. 在App2中处理加载与错误状态
提前拦截loading和error状态,避免将无效状态传递给子组件:
// 修改后的App2视图组件 import { Methods } from "../interfaces/request"; import Pokecard from "../components/pokecard/Pokecard"; import useAxios from "../plugins/Useaxios"; function App2() { const { response, loading, error } = useAxios({ method: Methods.get, url: "/ditto", body: JSON.stringify({}), headers: JSON.stringify({}), }); // 加载中显示占位 if (loading) return <div style={{ padding: "20px" }}>加载宝可梦数据中...</div>; // 请求错误显示提示 if (error) return <div style={{ padding: "20px", color: "red" }}>错误:{error}</div>; return ( <> <Pokecard response={response} /> </> ); } export default App2;
额外优化建议
- 移除App2中未使用的
data状态变量,简化代码结构; - 给
response添加TypeScript类型定义,避免any类型带来的潜在问题; - 若需缓存请求结果,可在
useAxios中添加缓存逻辑(比如使用useRef存储已请求过的url数据)。
内容的提问来源于stack exchange,提问作者David Pineda
相关产品推荐
相关产品推荐

