You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 14:20:22