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

useEffect空依赖数组仍无限运行 派发thunk加载表格数据问题咨询

问题根因

你代码里的两个错误直接导致了无限循环:

  • useEffect返回的清理函数格式错误:useEffect要求返回函数作为清理逻辑,你直接写return setDidFetch(false)等于在useEffect回调执行时同步立即触发状态修改,而非等到组件卸载时才执行。
  • 防抖状态未生效:你定义了didFetch用来避免重复请求,但useEffect内完全没有增加对应判断,请求没有被拦截。
    另外如果父组件传递的getCartItems是每次渲染都重新生成的匿名函数,也会进一步加重渲染循环问题。

修复方案

方案1:移除冗余的didFetch状态(更推荐)

空依赖的useEffect本身就只会在组件首次挂载时执行一次,不需要额外加防抖状态,同时把清理函数修正为函数格式:

const Cart = (props) => {
  useEffect( () => {
    async function fetchCart(){
      await props.getCartItems();
    }
    fetchCart()
    // 无清理逻辑可以省略返回,需要清理就包裹为函数
    // return () => { 你的清理逻辑 }
  },[]);

  return (
    <TableContainer component={Paper}>
      <Table sx={{ minWidth: 650 }} aria-label="simple table">
        <TableHead>
          <TableRow>
            <TableCell>Product</TableCell>
            <TableCell align="right">Quantity</TableCell>
            <TableCell align="right">Total Cost</TableCell>
          </TableRow>
        </TableHead>
        <TableBody>
          {props.cartItems.map((item) => (
            <TableRow
              key={item.product.name}
              sx={{ "&:last-child td, &:last-child th": { border: 0 } }}
            >
              <TableCell component="th" scope="row">
                {item.product.name}
              </TableCell>
              <TableCell align="right">{item.quantity}</TableCell>
              <TableCell align="right">
                {(item.quantity * item.product.price).toFixed(2)}
              </TableCell>
              <TableCell>
                <Button onClick={() => props.removeCartItem(item.id)}>
                  Remove
                </Button>
              </TableCell>
            </TableRow>
          ))}
        </TableBody>
      </Table>
    </TableContainer>
  );
};

如果eslint报getCartItems的依赖警告,在父组件用useCallback包裹传递的getCartItems方法保证引用稳定,再把稳定后的props.getCartItems加入useEffect依赖数组即可。

方案2:保留didFetch防抖逻辑

如果你需要主动控制请求时机,保留didFetch的话调整逻辑如下:

const Cart = (props) => {
  const [didFetch, setDidFetch] = useState(false);
  useEffect( () => {
    // 已经请求过直接跳过
    if (didFetch) return;
    async function fetchCart(){
      await props.getCartItems();
      setDidFetch(true);
    }
    fetchCart()
    // 清理逻辑包裹为函数,仅组件卸载时执行
    return () => setDidFetch(false)
  },[didFetch]);

  // 渲染逻辑和之前一致
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 19:15:03