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

