如何在onSubmit事件中传参调用React自定义Hook
核心结论
首先明确两点:
- 你当前写的
useAxios不适合表单提交场景,而且绝对不能在onSubmitForm这种事件回调里直接调用自定义Hook。React Hook有硬性调用规则:只能在函数组件、自定义Hook的顶层作用域调用,不能嵌在事件回调、条件判断、循环里执行。 - 你现在的Hook逻辑是组件挂载就自动在useEffect里发请求,根本没留手动触发的入口,天然匹配不了「用户点提交才发请求」的需求。
改造方案
把现有Hook改成支持手动触发调用的版本,把请求方法暴露出来,组件顶层拿到方法后,再到提交回调里执行即可。
改造后的useAxios
-- file useAxios.js -- import { useState, useCallback } from "react"; import axios from "axios"; const useAxios = (manual = false) => { const [response, setResponse] = useState(undefined); const [error, setError] = useState(""); // 手动模式下初始不需要加载状态 const [loading, setLoading] = useState(!manual); const run = useCallback(async (axiosParams) => { setLoading(true); setError(""); try { const result = await axios.request(axiosParams); setResponse(result.data); return result.data; } catch (err) { setError(err); throw err; } finally { setLoading(false); } }, []); return { response, error, loading, run }; }; export default useAxios;
改动点说明:
- 删掉了组件挂载就执行的useEffect,新增
manual入参标记是否为手动触发模式 - 把核心请求逻辑封装成
run方法对外暴露,调用时传入axios配置就能发请求 - 每次请求前重置错误状态,避免上一次请求的残留数据影响当前交互
- 增加返回值和错误抛出,方便你在请求结束后写成功/失败的后续逻辑(比如弹窗提示、页面跳转)
页面使用示例
在组件顶层调用Hook拿到run方法,提交表单时直接调用传参就行:
-- file Page.js -- import useAxios from "../hooks/useAxios"; function Page() { // 传true开启手动模式,组件加载时不会自动发请求 const { response, error, loading, run } = useAxios(true); const onSubmitForm = async (formValues) => { try { // 传入对应接口的配置参数 const submitRes = await run({ url: "/api/form/submit", method: "post", data: formValues }); // 这里写提交成功的逻辑,比如跳转到列表页、弹成功提示 console.log("提交成功", submitRes); } catch (err) { // 这里写提交失败的逻辑,比如弹错误提示 console.log("提交失败", err); } } return ( <form onSubmit={onSubmitForm}> {/* 你的表单字段 */} <button type="submit" disabled={loading}> {loading ? "提交中..." : "提交表单"} </button> {error && <div className="text-red-500">提交出错:{error.message}</div>} </form> ) }
补充
如果遇到页面加载就需要发请求的场景,不用改Hook,调用时不传manual参数,配合useEffect触发run就行,自动、手动两种请求场景都能兼容。
核心原则记牢:Hook本身永远在顶层调用,需要在事件、条件里触发的是Hook暴露出来的方法,不是Hook本身。
内容的提问来源于stack exchange,提问作者BibDev
相关产品推荐
相关产品推荐

