React管理面板首次加载API产品数据不显示,仅手动刷新后展示问题求解
问题根因
- React 状态更新是异步批量执行的,你在同一个函数作用域内调用
setProducts、setEditedItems后,立即读取的products、editedItems仍然是本次渲染周期的旧值,不会拿到刚更新的状态。你在判断逻辑里读取的products是初始的空数组,所以首次加载时allProducts被赋值为空,自然渲染不出来。 - useEffect 依赖为空数组时,内部捕获的
allProducts、editedItems永远是组件首次渲染时的初始值,逻辑判断不会随状态更新变化。 - 多余的无效赋值逻辑:你写的
setAllProducts(allProducts)、setAllProducts([...allProducts])完全没有实际作用,还会多余触发重渲染。
修复方案
直接使用接口返回的res.data做初始化,不要依赖刚更新完的状态,同时删除无效逻辑,加请求锁避免重复调用接口,修改后的Products组件代码如下:
import { useRef } from 'react' const Products = () => { const {products, setProducts, setAllProducts, allProducts, editedItems, setEditedItems} = useProduct(); // 加请求锁,避免重复拉取接口 const hasFetched = useRef(false); useEffect(() => { // 已经拉取过接口直接跳过 if (hasFetched.current) return; async function fetchProducts() { const res = await axios.get('https://a.nacapi.com/LimeGreen/products/').catch(err => console.log(err)); if(res) { hasFetched.current = true; const apiProducts = res.data; setProducts(apiProducts); setEditedItems(false); // 仅当本地没有产品数据、且用户未编辑过时,用接口数据初始化 if(allProducts.length === 0 && editedItems === false) { setAllProducts(apiProducts); } } return res; } fetchProducts(); // 把用到的状态加到依赖数组 }, [allProducts, editedItems, setProducts, setAllProducts, setEditedItems]); return ( <Wrapper classname="wrapper"> <h1>All Products</h1> <Cards> {!!allProducts.length && ( allProducts.map(product => ( <ProductCard name={product.name} description={product.Description} price={product.Price} discount={product.Discount} key={product.uuid}/> )) )} </Cards> </Wrapper> ) }
额外优化建议
如果需要严格避免接口重复请求,也可以把接口拉取逻辑移到ProductProvider里,应用初始化时只拉取一次,不用每个页面加载都调用接口。
内容的提问来源于stack exchange,提问作者evll
相关产品推荐
相关产品推荐

