当我尝试使用路由导航到我的页面时,我正在从 API 获取数据并将数组存储在“products”变量中并引用请求 URL 中的占位符参数,但是当我尝试导航到像“http:/ /localhost:3000/shoes/4' 应该返回带有未找到页面文本的页面,而不是详细信息页面。请说明为什么没有发生这种情况。
Json 服务器在 3001 端口
使用Fetch.js
import { useState, useEffect } from "react";
const baseUrl = "http://localhost:3001/";
export default function useFetch(url) {
const [data, setData] = useState(null);
const [error, setError] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetch(`${baseUrl}${url}`)
.then((response) => {
return response.json();
})
.then((data) => {
setData(data);
})
.catch((error) => {
setError(error);
})
.finally(() => {
setLoading(false);
});
}, [url]);
return { data, error, loading };
}
产品数组
{
"id": 1,
"category": "shoes",
"image": "shoe1.jpg",
"name": "Hiker",
"price": 94.95,
"skus": [
{ "sku": "17", "size": 7 },
{ "sku": "18", "size": 8 }
],
"description": "This rugged boot will get you up the mountain safely."
},
{
"id": 2,
"category": "shoes",
"image": "shoe2.jpg",
"name": "Climber",
"price": 78.99,
"skus": [
{ "sku": "28", "size": 8 },
{ "sku": "29", "size": 9 }
],
"description": "Sure-footed traction in slippery conditions."
},
{
"id": 3,
"category": "shoes",
"image": "shoe3.jpg",
"name": "Explorer",
"price": 145.95,
"skus": [
{ "sku": "37", "size": 7 },
{ "sku": "38", "size": 8 },
{ "sku": "39", "size": 9 }
],
"description": "Look stylish while stomping in the mud."
},
{
"id": 4,
"category": "headphone",
"image": "headphone3.jpg",
"name": "headphone red",
"price": 100,
"description": "Red colored headphone"
},
{
"id": 5,
"category": "headphone",
"image": "headphone2.jpg",
"name": "headphone blue",
"price": 90,
"description": "Blue colored headphone"
},
{
"id": 6,
"category": "headphone",
"image": "headphone1.jpg",
"name": "headphone black",
"price": 80,
"description": "Black colored headphone"
}
获取数据到产品数组
const { category, id } = useParams();
const { data: products, error, loading } = useFetch(
`products?category=${category}&id=${id}`
);
如果产品数组为空,则定向到找不到页面
if (products.length === 0) {
return <PageNotFound />;
}
使用路由定向到详细信息页面
<Route path="/:category/:id" element={<Detail />} />
答案 0 :(得分:0)
您将返回的 data
对象重命名为 products
,我确定您打算从 products
中解构嵌套的 data
数组。
const {
data: { products }, // <-- destructure products instead of rename data
error,
loading
} = useFetch(`products/${id}`);
现在 products.length
检查实际上将测试一个数组对象。
if (!products.length) {
return <PageNotFound />;
}
剩下的问题是呈现特定的“产品”或匹配的“产品”数组。这是您的代码有点奇怪的地方,因为您将类别和 id 都传递给 API 端点,而 fetch
不执行任何响应处理/过滤,它返回整个 JSON 响应。我在这里假设 UI 将处理 products
数组以匹配 category
和 id
的产品。
if (!products.length) return <PageNotFound />;
const product = products.find(
(product) => product.category === category && `${product.id}` === id
);
return (
<div id="detail">
<h1>{product.name}</h1>
<p>{product.description}</p>
<p id="price">${product.price}</p>
<img src={`/images/${product.image}`} alt={product.category} />
</div>
);
注意:如果您想在 useFetch
钩子中执行此操作并仍然返回一个数组,请使用 Array.prototype.filter
使用相同的条件并记住任何可呈现的内容仍将在一个数组中,因此您将需要映射结果或从 products
数组的前/后移动/弹出结果。
另一个问题是当 useFetch
更新并且效果再次运行时,您的 loading
钩子不会“重置”url
状态。此处的解决方法是给出初始错误的 loading
状态,并在获取开始时将其设置为真。
export default function useFetch(url) {
const [data, setData] = useState(products);
const [error, setError] = useState(null);
const [loading, setLoading] = useState(false); // <-- default false
useEffect(() => {
setLoading(true); // <-- toggle true when starting fetch
fetch(`${baseUrl}${url}`)
.then((response) => {
return response.json();
})
.then((data) => {
setData(data);
})
.catch((error) => {
setError(error);
})
.finally(() => {
setLoading(false);
});
}, [url]);
return { data, error, loading };
}