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

React中如何实现点击按钮重新触发useEffect执行?

你把removeFromCart作为useEffect依赖导致接口反复调用的核心原因是:组件每次渲染时,removeFromCart都会生成一个新的函数引用,只要依赖项变化useEffect就会执行,就会反复请求后端接口。

下面是3种可行的解决方案:

方案1:新增触发标识依赖(最直接满足「触发useEffect执行」的需求)

新增一个数字类型的状态作为useEffect的额外依赖,需要触发useEffect时就修改这个状态的值即可:

import React, { useContext, useEffect, useState,useCallback } from "react";
import { UserContext } from "./Context";
import { useHistory } from "react-router";
import cartImage from "../assets/man-shopping.png";
import Axios from "axios";

const Cart = () => {
  const { user, serUser } = useContext(UserContext);
  const history = useHistory();
  const [product, setProduct] = useState([]);
  // 新增触发标识
  const [cartRefresh, setCartRefresh] = useState(0);

  const removeFromCart = (item) => {
    Axios.delete(`http://localhost:3002/cart/${item.Id}`).then((res) => {
      // 删除成功后修改触发标识,让useEffect重新执行
      setCartRefresh(prev => prev + 1);
    });
  };

  useEffect(() => {
    // 边界判断,用户未登录时不请求
    if(!user?.Id) return;
    Axios.get(`http://localhost:3002/cart/${user.Id}`).then((res) => {
      setProduct(res.data);
    });
  // 依赖新增cartRefresh
  }, [user, cartRefresh]);

  // 原有return渲染逻辑保持不变,此处省略

这种方案的好处是,不管是添加商品、删除商品还是其他需要刷新购物车的场景,只需要调用setCartRefresh(prev => prev +1)就能触发接口重新拉取,逻辑统一。

方案2:直接封装拉取逻辑手动调用(适配当前场景的最优解)

其实不需要强制触发useEffect,完全可以把拉取购物车的逻辑单独抽出来,删除成功后直接调用即可:

const Cart = () => {
  const { user, serUser } = useContext(UserContext);
  const history = useHistory();
  const [product, setProduct] = useState([]);

  // 抽离拉取购物车逻辑,用useCallback保证引用稳定
  const fetchCart = useCallback(() => {
    if(!user?.Id) return;
    Axios.get(`http://localhost:3002/cart/${user.Id}`).then((res) => {
      setProduct(res.data);
    });
  }, [user]);

  const removeFromCart = (item) => {
    Axios.delete(`http://localhost:3002/cart/${item.Id}`).then((res) => {
      // 删除成功直接调用拉取接口
      fetchCart();
    });
  };

  // 组件挂载和user变化时拉取一次
  useEffect(() => {
    fetchCart();
  }, [fetchCart]);

  // 原有return渲染逻辑保持不变,此处省略

这个方案避免了多余的状态,逻辑更直观,性能也更好。

方案3:修复依赖函数引用问题(解决你之前尝试的方案的bug)

如果你还是想把removeFromCart加入依赖,只需要用useCallback包裹这个函数,保证它的引用稳定即可:

// 用useCallback包裹,保证函数引用稳定
const removeFromCart = useCallback((item) => {
  Axios.delete(`http://localhost:3002/cart/${item.Id}`).then((res) => {
    // setProduct用函数式更新,不需要依赖外部product变量
    setProduct(prevProduct => prevProduct.filter((item) => {
      return item.Id !== res.data.Id;
    }));
  });
}, []);

useEffect(() => {
  if(!user?.Id) return;
  Axios.get(`http://localhost:3002/cart/${user.Id}`).then((res) => {
    setProduct(res.data);
  });
}, [user, removeFromCart]);

注意这里setProduct用了函数式更新,所以removeFromCart的依赖项为空,引用不会随渲染变化,就不会导致useEffect反复触发。


内容的提问来源于stack exchange,提问作者gulam ahmad siddique

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 15:06:03