[英]How to delay page rendering until data received from api
当第一次使用 API 请求页面加载时,它会出错。 但是在页面加载后,如果我放回相同的代码,它就可以正常工作。 有人可以帮助我在这里缺少什么。 或者告诉我延迟页面加载的技巧,直到从 api 加载数据
import React, { useState, useEffect } from 'react'
export default function ProductPage({ data }) {
const [productData, setProductData] = useState(null)
useEffect(() => {
getProductdata()
}, [])
async function getProductdata(){
const secret = "SECRET"
const request = await fetch(`https://app.myapi.com/api/products/${data.productsCsv.id}`, {
headers: {
'Authorization': `Basic ${btoa(secret)}`,
'Accept': 'application/json'
}
}).then((request => request.json()))
.then(data => setProductData(data))
.catch(err=>console.log(err))
}
console.log("pdata",productData) // returns null on initial load and then it filled with data.
return (
<>
<div className="stock mb-4 ">
<p className="tracking-wider mb-2">Size</p>
{productData.variants.map((variant,index)=>{
<p>{variant.stock}</p>
if(variant.stock != 0){
return (
<button className={`p-2 border-gray-200 border mr-2 mb-2 hover:bg-black hover:text-white cursor-pointer focus:border-black ${activeSize === index ? 'bg-black text-white' : null}`} role="button" tabIndex={0}
onClick={() => {toggleSize(index); setSize(size)}}
onKeyDown={() => {toggleSize(index); setSize(size)}} key={index}>{variant.variation[0].option}-{variant.stock}</button>
)
}
else {
return(
<button className={`p-2 border-gray-200 border mr-2 mb-2 ${variant.stock == 0 ?'bg-gray-400 line-through text-red-500': null}`} disabled role="button" tabIndex={0}
onClick={() => {toggleSize(index); setSize(size)}}
onKeyDown={() => {toggleSize(index); setSize(size)}} key={index}>{variant.variation[0].option}-{variant.stock}</button>
)
}
})}
</div>
</>
)
设置一点 state 并返回另一个组件,直到你有你的数据,它应该看起来像这样:
import React, { useState, useEffect } from 'react'
export default function ProductPage({ data }) {
const [productData, setProductData] = useState(null)
const [loading, setLoading] = useSate(true) // set some state for loading
useEffect(() => {
getProductdata()
}, [])
async function getProductdata(){
const secret = "SECRET"
const request = await fetch(`https://app.myapi.com/api/products/${data.productsCsv.id}`, {
headers: {
'Authorization': `Basic ${btoa(secret)}`,
'Accept': 'application/json'
}
}).then((request => request.json()))
.then((data) => {
setProductData(data)
setLoading(false) // set Loading to false when you have the data
})
.catch(err=>console.log(err))
}
//use the piece of loading state to return other component until you have the data
if (loading) {
return (<div>Replace me with a loading component...</div>)
}
return (
<>
...
</>
)
您的productData
最初是null
并将在任何后续渲染中出现,直到被 GET 请求更新。 尝试访问productData.variants
会引发错误,因为productData
是 null。
您可以使用一些加载 state 并有条件地渲染您的 UI。 在productData
state 上使用空值检查/可选链接运算符。
const [productData, setProductData] = useState(null);
const [isLoading, setIsLoading] = useState(true); // <-- loading state
useEffect(() => {
getProductdata();
}, []);
async function getProductdata() {
setIsLoading(true); // <-- ensure loading true
const secret = "SECRET";
const request = await fetch(
`https://app.myapi.com/api/products/${data.productsCsv.id}`,
{
headers: {
'Authorization': `Basic ${btoa(secret)}`,
'Accept': 'application/json'
}
}
).then((request => request.json()))
.then(data => setProductData(data))
.catch(err => console.log(err))
.finally(() => setIsLoading(false); // <-- clear loading state success or fail
}
if (isLoading) return <div>Loading Data</div>; // <-- render loading UI
return (
...
{productData?.variants?.map(......)}
...
);
它是 null 因为它在你的 useState 挂钩中被初始化为 null。 这个是正常的。
useEffect 挂钩应如下所示。
useEffect(() => {
function getProductdata() {
const secret = "SECRET"
return fetch(`https://app.myapi.com/api/products/${data.productsCsv.id}`, {
headers: {
'Authorization': `Basic ${btoa(secret)}`,
'Accept': 'application/json'
}
});
}
getProductdata().then((request => request.json()))
.then(data => setProductData(data))
.catch(err=>console.log(err));
}, []);
您可以通过在模板中使用逻辑 AND && 运算符来检查变量是否不是 null 来阻止显示数据。
{productData && productData.variants.map((variant,index)=> ...
我没有测试这段代码。
旁注:秘密不是秘密。 它将出现在代码中。
您收到此错误是因为productData.variants
不存在,因此 map function 返回错误。 在 map function 之前添加检查productData
的条件语句。
{productData ? (
productData.variants.map((variant,index)=>{
//rest of code
}
) : null}
因此,如果productData
为null
,则 map function 不会执行。 这是一个三元运算符,在编写 ReactJS 时非常有用。
您甚至可以添加<p>Loading Data</p>
而不仅仅是null
,以便用户知道正在加载数据而不是空白区域:
{productData ? (
productData.variants.map((variant,index)=>{
//rest of code
}
) : (
<p>Loading Data...</p>
)}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.