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

如何在onSubmit事件中传参调用React自定义Hook

核心结论

首先明确两点:

  1. 你当前写的useAxios不适合表单提交场景,而且绝对不能在onSubmitForm这种事件回调里直接调用自定义Hook。React Hook有硬性调用规则:只能在函数组件、自定义Hook的顶层作用域调用,不能嵌在事件回调、条件判断、循环里执行。
  2. 你现在的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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 19:48:29