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

React使用useEffect时出现无限重复请求问题的解决方法

问题根因

接口无限重复请求的核心原因是React useEffect 对依赖项做引用相等校验,而非值相等校验:

  • 你在App组件的函数体内直接定义了params对象,组件每一次重渲染都会生成一个全新引用的params对象
  • 自定义Hook里的useEffect把params作为依赖项,每次拿到新引用的params都会触发effect执行,调用接口
  • 接口请求完成后调用setData、setLoading会触发组件重渲染,又会生成新的params对象,再次触发effect,形成死循环
修复方案

可以从调用侧、Hook侧两个维度修复,推荐两侧都做处理,鲁棒性更强:

方案1:调用侧缓存参数对象

对于固定不变的请求参数,用useMemo缓存,避免每次渲染生成新引用:

import { useMemo } from 'react';
import { useRequest } from "./hooks/useRequest";

function App() {
  // 仅当依赖数组内的值变化时,才会重新生成params对象
  const params = useMemo(() => ({
    pagination: { page: 1, perPage: 10 },
    sort: { field: "updatedAt", order: "DESC" },
  }), []); // 如果参数有动态值,把对应的变量加到依赖数组即可
  const { data, loading } = useRequest("/posts", params);

  return (
    <Layout>
      <div className="text-white"></div>
    </Layout>
  );
}

export default App;

方案2:Hook侧优化依赖逻辑

不要直接把整个对象/数组作为依赖项,拆解为基本类型值做依赖,同时缓存请求函数,避免不必要的触发:

import { useState, useEffect, useCallback } from 'react';
// 保留你原有引入的依赖
// import { stringify } from 'xxx';
// import http from 'xxx';

export const useRequest = (resource, params) => {
  const [data, setData] = useState();
  const [loading, setLoading] = useState(false);

  // 缓存请求函数,仅当resource变化时才重新生成
  const fetcher = useCallback((currentParams) => {
    setLoading(true);
    const { page, perPage } = currentParams.pagination;
    const { field, order } = currentParams.sort;
    const query = {
      sort: JSON.stringify([field, order]),
      range: JSON.stringify([(page - 1) * perPage, page * perPage - 1]),
      filter: JSON.stringify(currentParams?.filter ? currentParams.filter : ""),
    };

    http.get(`${resource}?${stringify(query)}`).then((res) => {
      setData(res);
      setLoading(false);
    });
  }, [resource]);

  useEffect(() => {
    // 增加参数合法性校验,避免参数缺失时报错
    if (!params?.pagination || !params?.sort) return;
    fetcher(params);
    // 依赖项拆解为基本类型,值不变就不会重复触发effect
  }, [
    fetcher,
    params.pagination?.page,
    params.pagination?.perPage,
    params.sort?.field,
    params.sort?.order,
    params.filter
  ]);

  return {
    data,
    loading,
  };
};

补充:如果参数嵌套层级很深,拆解依赖太繁琐,也可以用JSON.stringify(params)序列化后的字符串作为依赖项,注意保证对象键顺序固定即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 03:06:23