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

React项目中Fetch请求失败问题排查求助

问题

开发网站时遇到Fetch请求失败,报错信息如下:

Failed to fetch TypeError: Failed to fetch
at getItems (http://localhost:3000/main.b060b3b85b623d5e4359.hot-update.js:47:25)
at http://localhost:3000/main.b060b3b85b623d5e4359.hot-update.js:54:5
at commitHookEffectListMount (http://localhost:3000/static/js/bundle.js:50177:30)
at commitPassiveMountOnFiber (http://localhost:3000/static/js/bundle.js:51670:17)
at commitPassiveMountEffects_complete (http://localhost:3000/static/js/bundle.js:51642:13)
at commitPassiveMountEffects_begin (http://localhost:3000/static/js/bundle.js:51632:11)
at commitPassiveMountEffects (http://localhost:3000/static/js/bundle.js:51622:7)
at flushPassiveEffectsImpl (http://localhost:3000/static/js/bundle.js:53507:7)
at flushPassiveEffects (http://localhost:3000/static/js/bundle.js:53459:18)
at commitRootImpl (http://localhost:3000/static/js/bundle.js:53418:9)

相关代码:

import React, { useEffect, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { Box, Typography, Tab, Tabs, useMediaQuery } from "@mui/material";
import { setItems } from "../../state";
import Item from "../../components/item";

const ShoppingList = () => {
  const dispatch = useDispatch();
  const [value, setValue] = useState("all");
  const items = useSelector((state) => state.cart.items);
  const isNonMobile = useMediaQuery("(min-width:600px)");
  console.log("items", items);

  const handleChange = (event, newValue) => {
    setValue(newValue);
  };

  async function getItems() {
    const items = await fetch(
      "https://localhost:1337/api/items?populate=image",
      { method: "GET" }
    );
    const itemsJson = await items.json();
    dispatch(setItems(itemsJson.data));
  }

  useEffect(() => {
    getItems();
  }, []); // eslint-disable-line react-hooks/exhaustive-deps

  const topRatedItems = items.filter(
    (item) => item.attributes.category === "topRated"
  );
  const newArrivalsItems = items.filter(
    (item) => item.attributes.category === "newArrivals"
  );
  const bestSellersItems = items.filter(
    (item) => item.attributes.category === "bestSellers"
  );

  return (
    <Box width="80%" margin="80px auto">
      <Typography variant="h3" textAlign="center">
        Our Featuted <b>Products</b>
      </Typography>
      <Tabs
        textColor="primary"
        indicatorColor="primary"
        value={value}
        onChange={handleChange}
        centered
        TabIndicatorProps={{ sx: { display: isNonMobile ? "block" : "none" } }}
        sx={{
          m: "25px",
          "& .MuiTabs-flexContainer": {
            flexWrap: "wrap",
          },
        }}
      >
        <Tab label="ALL" value="all" />
        <Tab label="NEW ARRIVALS" value="newArrivals" />
        <Tab label="BEST SELLERS" value="bestSellers" />
        <Tab label="TOP RATED" value="topRated" />
      </Tabs>
      <Box
        margin="0 auto"
        display="grid"
        gridTemplateColumns="repeat(auto-fill, 300px)"
        justifyContent="space-around"
        rowGap="20px"
        columnGap="1.33%"
      >
        {value === "all" &&
          items.map((item) => (
            <Item item={item} key={`${item.name}-${item.id}`} />
          ))}
        {value === "newArrivals" &&
          newArrivalsItems.map((item) => (
            <Item item={item} key={`${item.name}-${item.id}`} />
          ))}
        {value === "bestSellers" &&
          bestSellersItems.map((item) => (
            <Item item={item} key={`${item.name}-${item.id}`} />
          ))}
        {value === "topRated" &&
          topRatedItems.map((item) => (
            <Item item={item} key={`${item.name}-${item.id}`} />
          ))}
      </Box>
    </Box>
  );

  return <div>shopping list</div>;
};

export default ShoppingList;

排查与解决

  • 检查后端服务状态:直接在浏览器地址栏访问https://localhost:1337/api/items?populate=image,确认后端服务是否正常运行并返回数据。如果无法访问,先启动对应端口的后端服务。
  • 修正协议不匹配问题:前端运行在http://localhost:3000,但请求使用https://localhost:1337,若后端未配置HTTPS,将请求地址改为http://localhost:1337/api/items?populate=image。
  • 处理跨域限制:若前后端端口不同,需在后端配置CORS规则(比如Strapi可在后台设置中添加http://localhost:3000到允许访问的域名列表)。
  • 添加错误捕获逻辑:当前代码未处理Fetch请求的错误情况,修改getItems函数,便于定位具体问题:
    async function getItems() {
      try {
        const items = await fetch(
          "http://localhost:1337/api/items?populate=image",
          { method: "GET" }
        );
        if (!items.ok) {
          throw new Error(`HTTP错误!状态码: ${items.status}`);
        }
        const itemsJson = await items.json();
        dispatch(setItems(itemsJson.data));
      } catch (error) {
        console.error('获取商品数据失败:', error);
      }
    }
    
  • 删除冗余代码:组件中存在两个return语句,最后一个永远不会执行,删除return <div>shopping list</div>避免逻辑混乱。

内容的提问来源于stack exchange,提问作者sylo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 12:42:50