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

