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

React中如何在首次渲染与表单校验中复用自定义useQuery钩子?

解决方案

首先明确核心限制:React钩子(包括你自定义的useSomethingQuery)只能在组件或其他自定义钩子的顶层调用,不能在useEffect、校验器这类嵌套函数内使用。我们可以通过以下方式复用useQuery的逻辑,同时满足首次渲染和校验器的需求:

1. 组件顶层调用自定义钩子

在组件最外层调用useSomethingQuery,获取数据、手动刷新方法和加载状态:

import { useState, useEffect } from 'react';
import { Form } from 'antd';
import { useSomethingQuery } from './your-hooks-path';

const YourFormComponent = ({ someIdFromProps }) => {
  const [someBooleanState, setSomeBooleanState] = useState<boolean>(false);
  // 顶层调用自定义钩子,依赖someIdFromProps自动触发首次请求
  const { 
    data: things, 
    refetch, // 手动触发请求的方法
    isLoading, // 加载状态
    error // 请求错误信息
  } = useSomethingQuery(someIdFromProps);

2. 替代原useEffect逻辑

利用useEffect监听useQuery返回的data变化,自动更新someBooleanState,替代原来手动写的请求逻辑:

// 当things数据更新时,计算并更新状态
  useEffect(() => {
    if (things) {
      const someBoolean = things.some(item => item.someProp === 'SOME_VALUE');
      setSomeBooleanState(someBoolean);
    }
  }, [things]);

3. 改造校验器逻辑

校验器内不能调用钩子,但可以使用useQuery提供的refetch方法手动触发请求(复用缓存和请求逻辑),完成校验:

// 定义校验器函数
  const uploadValidator = async () => {
    // 可选:如果缓存已有数据,直接用缓存;否则手动刷新
    let targetThings = things;
    if (!targetThings) {
      const refetchResult = await refetch();
      targetThings = refetchResult.data;
    }

    if (!targetThings) {
      // 请求失败的情况,直接返回错误
      return Promise.reject(new Error('Failed to fetch necessary data'));
    }

    const someBoolean = targetThings.some(item => item.someProp === 'SOME_VALUE');
    setSomeBooleanState(someBoolean);
    
    return someBoolean 
      ? Promise.resolve() 
      : Promise.reject(new Error('Please upload a file with certain thing'));
  };

4. 渲染表单组件

最后把校验器绑定到Form.Item的规则中:

return (
    <Form>
      {/* 处理加载/错误状态(可选) */}
      {isLoading && <div>Loading...</div>}
      {error && <div>Error: {error.message}</div>}

      <Form.Item
        name="upload"
        label="Upload File"
        rules={[
          { required: true, message: 'Please upload a file' },
          { validator: uploadValidator }
        ]}
      >
        {/* 你的文件上传组件 */}
      </Form.Item>
    </Form>
  );
};

export default YourFormComponent;

关键说明

  • useQuery会自动在组件首次渲染、queryKey(这里是['something', someIdFromProps])变化时发起请求,无需手动在useEffect中写请求逻辑。
  • refetch方法可以在任意回调函数中调用,既复用了useSomethingQuery的请求逻辑,又符合React钩子规则。
  • 如果校验时允许使用缓存数据,可以跳过refetch直接用things,提升性能;如果必须获取最新数据,则调用refetch。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 06:05:22