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

如何复用useFetch Hook实现POST请求?当前为组件渲染触发而非动作触发

解决方案

要让你的useFetch Hook既能支持组件初始加载时的自动请求,又能手动触发POST表单提交,你可以通过抽离独立的请求函数、新增自动触发开关来实现。以下是修改后的完整代码:

import { useState, useEffect } from 'react';

const useFetch = (url: string, initialConfig: RequestInit = {}, autoFetch = true) => {
  const [isLoading, setIsLoading] = useState(false);
  const [data, setData] = useState<any>(null);
  const [error, setError] = useState<string | null>(null);

  // 抽离独立的请求逻辑,支持动态传入url和config
  const fetchData = async (customUrl?: string, customConfig?: RequestInit) => {
    setIsLoading(true);
    setError(null);
    try {
      const targetUrl = customUrl || url;
      const targetConfig = { ...initialConfig, ...customConfig };
      
      const res = await fetch(targetUrl, targetConfig);
      if (!res.ok) {
        const errData = await res.json();
        throw new Error(JSON.stringify(errData));
      }
      const responseData = await res.json();
      setData(responseData);
    } catch (e: any) {
      setError(e.message || '请求失败');
    } finally {
      setIsLoading(false);
    }
  };

  // 初始加载时自动触发(仅当autoFetch为true时)
  useEffect(() => {
    if (autoFetch) {
      fetchData();
    }
  }, [url, initialConfig, autoFetch]);

  return { data, isLoading, error, fetchData };
};

export default useFetch;

关键修改点说明

  1. 抽离独立的fetchData函数:把请求逻辑从useEffect中抽出来,允许手动调用,同时支持传入自定义的url和config,灵活适配POST场景。
  2. 新增autoFetch参数:默认值为true,保持原有初始加载自动请求的行为;当需要手动触发POST时,设为false即可避免自动请求。
  3. 优化错误处理:原代码中throw new Error(JSON.stringify(res.json()))存在异步处理问题,现在改为先等待错误数据解析后再抛出,确保错误信息准确。
  4. 合并配置:手动调用时,自定义配置会和初始配置合并,方便复用基础配置(比如统一的headers)。

使用示例

1. 原有初始加载GET请求(保持不变)

const { data, isLoading, error } = useFetch('/api/data');

2. 手动触发POST表单提交

const { data, isLoading, error, fetchData } = useFetch('/api/submit', {}, false);

const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
  e.preventDefault();
  const formData = new FormData(e.currentTarget);
  
  await fetchData('/api/submit', {
    method: 'POST',
    body: formData
    // 注意:提交FormData时不需要手动设置Content-Type,浏览器会自动添加正确的multipart/form-data头
  });
  
  // 请求完成后可以根据data或error做后续处理
  if (!error) {
    alert('提交成功');
  }
};

// 表单JSX
<form onSubmit={handleSubmit}>
  {/* 表单控件 */}
  <button type="submit" disabled={isLoading}>
    {isLoading ? '提交中...' : '提交'}
  </button>
</form>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 21:53:16