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

React项目在回调内调用useAxios触发Hook规则报错该如何修复?

问题根因
  • 违反React Hooks调用规则:React Hook必须在函数组件的顶层作用域调用,不能在事件回调、循环、条件判断等非顶层场景调用。你将useAxios的调用放在表单提交的onFinish回调函数中,直接触发了react-hooks/rules-of-hooks校验规则,所以报错。
  • 现有useAxios设计不符合登录场景的需求:原有代码逻辑是Hook调用时就自动发起请求,但是登录请求需要用户填写完信息点击提交按钮后才触发,不能进入页面就自动发送。
  • 额外隐藏问题:原有useAxios中axios的传参顺序错误,post类请求的第二个参数是请求体body,第三个才是配置项headers,原代码顺序写反会导致请求参数传递异常。
修复方案

第一步:改造useAxios支持手动触发请求

调整Hook逻辑,新增自动请求开关,暴露请求方法供手动调用,同时修复参数顺序问题:

import { useState, useCallback, useEffect } from 'react';
import axios from 'axios';

axios.defaults.baseURL = 'http://localhost:3000/';

const useAxios = ({ url, method, body = null, headers = null, auto = true }) => {
  const [response, setResponse] = useState(null);
  const [error, setError] = useState('');
  const [loading, setLoading] = useState(false);

  const fetchData = useCallback(async (customBody = body) => {
    setLoading(true);
    setError('');
    try {
      let res;
      if (method.toLowerCase() === 'get') {
        res = await axios[method](url, headers);
      } else {
        res = await axios[method](url, customBody, headers);
      }
      setResponse(res.data);
      return res.data;
    } catch (err) {
      setError(err);
      throw err;
    } finally {
      setLoading(false);
    }
  }, [method, url, body, headers]);

  useEffect(() => {
    if (auto) {
      fetchData();
    }
  }, [fetchData, auto]);

  return { response, error, loading, fetchData };
};

export default useAxios;

第二步:改造登录组件调用逻辑

在组件顶层调用useAxios,提交表单时调用暴露出来的请求方法即可:

import React from 'react';
import { Form, Input, Button, message } from 'antd';
import useAxios from '../hooks/useAxios';

const LoginForm = () => {
  // 组件顶层调用Hook,关闭自动请求开关
  const { fetchData: login, loading } = useAxios({
    url: 'api/auth/login',
    method: 'post',
    auto: false
  });

  const onFinish = async (body) => {
    try {
      const loginResult = await login(body);
      console.log('登录成功', loginResult);
      // 此处可添加登录成功后的跳转、存储token等逻辑
    } catch (err) {
      console.error('登录失败', err);
      message.error('账号或密码错误');
    }
  };

  const findIDAndPassword = () => {
    console.log('findIDAndPassword');
  };

  return (
    <Form name="basic" onFinish={onFinish} autoComplete="off">
      <Form.Item
        name="id"
        rules={[
          {
            required: true,
            message: '请输入账号!',
          },
        ]}
      >
        <Input placeholder="ID" />
      </Form.Item>
      <Form.Item
        name="password"
        rules={[
          {
            required: true,
            message: '请输入密码!',
          },
        ]}
      >
        <Input.Password placeholder="PASSWORD" />
      </Form.Item>
      <Form.Item>
        <Button type="primary" htmlType="submit" block loading={loading}>
          登录
        </Button>
      </Form.Item>
      <Button type="link" block onClick={findIDAndPassword}>
        找回账号密码
      </Button>
    </Form>
  );
};

export default LoginForm;

内容的提问来源于stack exchange,提问作者고윤태

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 09:15:04