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

React自定义Fetch Hook遇规则违规,求修改建议

React Hooks规则违规问题修复:自定义useFetch Hook的正确用法

首先明确说:你的useFetch Hook本身逻辑没大问题,但调用位置完全错了,这才触发了Hooks规则的报错。

问题根源

你在MedicineContainer组件函数的外部调用了useFetch:

// 错误:Hooks不能在组件函数外部调用
const res = useFetch('http://localhost:5000/api/medicines', {});
export default MedicineContainer;

React Hooks的核心规则就是:必须在React函数组件的顶层作用域调用Hooks,不能在组件外、条件判断、循环、嵌套函数里使用——React靠调用顺序来追踪Hooks的状态,打乱顺序或者在非顶层调用都会导致状态追踪混乱。

修正步骤

1. 调整useFetch的调用位置

把useFetch的调用移到MedicineContainer组件的顶层作用域里,替换掉原来手动写的useEffect和useState逻辑:

import React from 'react';
import useFetch from '../../Helpers/Custom useFetch()';
import MedicineList from './MedicineUI';

const MedicineContainer = () => {
  // 正确:在组件顶层调用自定义Hook
  const { response: medicineLists, error, isLoading } = useFetch('http://localhost:5000/api/medicines', {});

  // 可以根据isLoading和error添加状态提示
  if (isLoading) return <div>加载中...</div>;
  if (error) return <div>加载失败:{error.message}</div>;

  return <MedicineList medicineList={medicineLists || []} />;
};

export default MedicineContainer;

2. 优化useFetch Hook本身

你的useFetch还有两个小问题可以优化:

  • 混用了React.useState和直接导入的useState,统一风格更清晰
  • 捕获错误时没有把isLoading设为false,会导致出错后加载状态一直挂着

优化后的useFetch代码:

import { useEffect, useState } from 'react';

const useFetch = (url, options) => {
  const [response, setResponse] = useState(null);
  const [error, setError] = useState(null);
  const [isLoading, setIsLoading] = useState(false);

  useEffect(() => {
    const fetchData = async () => {
      setIsLoading(true);
      try {
        const res = await fetch(url, options);
        const json = await res.json();
        setResponse(json);
      } catch (error) {
        setError(error);
      } finally {
        // 不管成功失败,都结束加载状态
        setIsLoading(false);
      }
    };

    fetchData();
  }, [options, url]);

  return { response, error, isLoading };
};

export default useFetch;

补充说明

  • 记住Hooks的两个核心规则:
    1. 只在React函数组件或自定义Hook的顶层调用Hooks
    2. 不要在条件、循环、嵌套函数里调用Hooks
  • 自定义Hook的命名必须以use开头,你的useFetch符合要求,这点没问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 18:27:54