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

React依赖数组报错,Post方法失效,useCallback依赖问题求助

修复useHttp自定义Hook的依赖警告与功能问题

原代码存在的核心问题

  • init对象重复创建导致依赖失效:组件每次渲染时,init都会被重新声明为新对象,导致useCallback的依赖数组变化,触发http函数反复重建,进而让useEffect重复执行。
  • 渲染阶段调用setBody引发无限循环:直接在函数体中调用setBody会触发状态更新,导致组件反复渲染,陷入循环。
  • fetch参数格式错误:fetch的第二个参数是配置对象,原代码错误地将body单独作为参数传入。
  • Get/Post逻辑未区分处理:Get请求不需要发送body,原代码未做区分,可能导致无效请求。

修复后的完整代码

import { useCallback, useEffect, useState, useMemo } from 'react'

const useHttp = (url) => {
  const [data, setData] = useState(null);
  const [error, setError] = useState(null);
  const [loading, setLoading] = useState(true);
  const [method, setMethod] = useState('get');
  const [requestBody, setRequestBody] = useState(null);

  // 用useMemo缓存init,仅当method变化时重新生成
  const init = useMemo(() => ({
    method: method.toLowerCase(),
    headers: {
      "Content-Type": "application/json"
    }
  }), [method]);

  const http = useCallback(async () => {
    // 重置请求状态
    setLoading(true);
    setError(null);
    setData(null);

    try {
      const fetchOptions = { ...init };
      // 非GET请求且存在body时,才添加序列化后的body
      if (method.toLowerCase() !== 'get' && requestBody) {
        fetchOptions.body = JSON.stringify(requestBody);
      }

      const res = await fetch(url, fetchOptions);
      if (!res.ok) {
        throw new Error("Ops! There was an error. Check connection or report to Admin");
      }
      const responseData = await res.json();
      setData(responseData);
    } catch (err) {
      setError(err.message);
    } finally {
      setLoading(false);
    }
  }, [url, init, method, requestBody]);

  useEffect(() => {
    http();
  }, [http]);

  return { data, error, loading, setRequestBody, setMethod };
}

export default useHttp;

关键修复说明

  1. 用useMemo缓存init对象:将init的创建逻辑包裹在useMemo中,依赖仅为method,确保只有请求方法变化时才重新生成init,解决useCallback的依赖警告。
  2. 移除渲染阶段的状态更新:把body的序列化逻辑移到http函数内部,仅在发起请求时处理,彻底避免无限循环。同时重命名状态为requestBody,避免与fetch的body参数混淆。
  3. 修正fetch调用格式:将body合并到fetch的配置对象中,严格遵循fetch API的参数要求。
  4. 区分Get/Post请求:Get请求自动跳过body设置,符合HTTP规范;Post请求则自动序列化传入的requestBody。
  5. 优化异步逻辑:改用async/await替代then/catch链,代码更易读,同时修复原代码中未解析响应数据的问题。
  6. 请求前重置状态:每次发起请求前重置loading、error和data,避免上次请求的状态残留影响当前请求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 15:01:11