You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 00:41:01