React组件WarehouseSelect重复请求数据优化实现咨询
解决WarehouseSelect重复请求仓库数据的问题
问题根源
你当前的代码中,每个WarehouseSelect组件实例挂载时,都会检查自己内部的warehouses状态——如果会话存储里还没数据,多个组件就会同时发起请求,导致重复调用接口。
方案一:组件内添加防重复请求逻辑
直接修改WarehouseSelect组件,增加加载状态并优先检查会话存储,避免重复请求:
import { useState, useEffect } from 'react'; import axios from 'axios'; import { Select, SelectItem } from '@your-ui-library'; // 替换成你的UI库 import { useSessionStorage } from './your-hooks'; // 你的自定义Hook export default function WarehouseSelect( {warehouse, setWarehouse}: { warehouse: number; setWarehouse: React.ChangeEventHandler<HTMLSelectElement>} ) { const [warehouses, setWarehouses] = useSessionStorage<Warehouse[]>('warehouses', []); const [isLoading, setIsLoading] = useState(false); // 新增加载状态,防止重复请求 useEffect(() => { // 先检查会话存储里是否已有仓库数据 const storedWarehouses = window.sessionStorage.getItem('warehouses'); if (storedWarehouses) { const parsed = JSON.parse(storedWarehouses); if (parsed.length > 0) return; } // 如果已有数据或正在加载,直接返回 if (warehouses.length > 0 || isLoading) return; setIsLoading(true); axios.get("/api/warehouses") .then((response) => setWarehouses(response.data.data)) .finally(() => setIsLoading(false)); // 请求完成后重置加载状态 }, [warehouses, isLoading]) return ( <Select isRequired label="Warehouse" placeholder="Select Warehouse" radius="none" value={warehouse} onChange={setWarehouse} items={warehouses.length ? warehouses : undefined} isLoading={isLoading} // 可选:给Select添加加载状态提示 > {(wh) => <SelectItem key={wh.id}>{wh.name}</SelectItem> } </Select> ); }
方案二:全局共享仓库数据(更优解)
如果多个组件都需要仓库数据,建议把数据获取逻辑抽离到全局Context中,确保只加载一次:
1. 创建仓库Context和Provider
// WarehouseContext.tsx import { createContext, useContext, useState, useEffect } from 'react'; import { useSessionStorage } from './your-hooks'; import axios from 'axios'; interface Warehouse { id: number; name: string; } const WarehouseContext = createContext<{ warehouses: Warehouse[]; isLoading: boolean; }>({ warehouses: [], isLoading: false }); export function WarehouseProvider({ children }: { children: React.ReactNode }) { const [warehouses, setWarehouses] = useSessionStorage<Warehouse[]>('warehouses', []); const [isLoading, setIsLoading] = useState(false); useEffect(() => { const stored = window.sessionStorage.getItem('warehouses'); if (stored && JSON.parse(stored).length) return; if (warehouses.length || isLoading) return; setIsLoading(true); axios.get("/api/warehouses") .then(res => setWarehouses(res.data.data)) .finally(() => setIsLoading(false)); }, [warehouses, isLoading]); return ( <WarehouseContext.Provider value={{ warehouses, isLoading }}> {children} </WarehouseContext.Provider> ); } export const useWarehouses = () => useContext(WarehouseContext);
2. 在顶层组件包裹Provider
比如在App.tsx中:
import { WarehouseProvider } from './WarehouseContext'; function App() { return ( <WarehouseProvider> {/* 你的页面组件,包含所有需要用到WarehouseSelect的地方 */} </WarehouseProvider> ); }
3. 简化WarehouseSelect组件
// WarehouseSelect.tsx import { Select, SelectItem } from '@your-ui-library'; import { useWarehouses } from './WarehouseContext'; export default function WarehouseSelect( {warehouse, setWarehouse}: { warehouse: number; setWarehouse: React.ChangeEventHandler<HTMLSelectElement>} ) { const { warehouses, isLoading } = useWarehouses(); return ( <Select isRequired label="Warehouse" placeholder="Select Warehouse" radius="none" value={warehouse} onChange={setWarehouse} items={warehouses.length ? warehouses : undefined} isLoading={isLoading} > {(wh) => <SelectItem key={wh.id}>{wh.name}</SelectItem> } </Select> ); }
这样不管页面里有多少个WarehouseSelect组件,仓库数据只会加载一次,彻底解决重复请求问题。
内容的提问来源于stack exchange,提问作者Shahadat Hossain
相关产品推荐
相关产品推荐

