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

自定义hook中传入useQuery的对象数组调用时为空如何解决?

问题根因

这是典型的闭包陷阱问题,同时属于React Query的用法错误:

  • 首次调用useAddNewEventsData自定义Hook时,newEvents是初始的空数组,useQuery的查询函数() => AddNewEvents(newEvents)会直接捕获这个初始的空数组值存入闭包
  • 后续你更新newEvents状态时,因为queryKey固定写死为'add-new-events-query'没有变化,React Query不会重建查询函数,闭包中存储的还是最初的空数组
  • 调用refetch()时执行的还是旧闭包中的函数,所以拿到的参数永远是空数组

额外说明:POST请求属于数据写入操作,本来就不应该用useQuery实现,useQuery是专门为GET类的数据查询场景设计的,写入操作请使用React Query提供的useMutation。

修复方案

方案1:调整queryKey(临时适配useQuery的写法)

把newEvents加入queryKey数组,只要newEvents更新,queryKey就会变化,React Query会自动重建查询函数,捕获最新的参数值:

export const useAddNewEventsData = (newEvents, onSuccess, onError) => {
    console.log('before arrow function: ', newEvents);
    return useQuery(['add-new-events-query', newEvents], () => AddNewEvents(newEvents), {
        onSuccess: onSuccess,
        onError: onError,
        enabled: false,
    });
};

如果newEvents是引用类型,每次状态更新都会生成新的引用,会触发queryKey变化,符合需求。

方案2:改用useMutation(推荐,符合React Query设计规范)

写入类操作使用useMutation,天然不需要提前绑定参数,调用mutate的时候直接传入最新的参数即可:
首先修改自定义Hook:

// 自定义hook代码
const AddNewEvents = async (newEvents) => {
    console.log('AddNewEvents fn: ', newEvents);
    return await axios.post(`${process.env.REACT_APP_API_URL}Event`, newEvents);
};

export const useAddNewEventsData = (onSuccess, onError) => {
    return useMutation(AddNewEvents, {
        onSuccess: onSuccess,
        onError: onError,
    });
};

然后在App.js中使用:

const [newEvents, setNewEvents] = useState([]);

const addNewEventsResp = useAddNewEventsData(
    onSuccessUseAddNewEventsData,
    onErrorUseAddNewEventsData
);

// 填充完newEvents后调用触发请求
const handleSubmit = () => {
    addNewEventsResp.mutate(newEvents);
};

这种方案完全规避了闭包问题,也是React Query官方推荐的增删改操作的实现方式。

内容的提问来源于stack exchange,提问作者Jason Tan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 23:54:03