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

React+TypeScript项目useEffect依赖及组件卸载状态更新报错修复

仓鼠投票小游戏控制台报错修复方案

报错1:useEffect依赖变动告警

  • 报错原因:sendRequest函数定义在组件顶层,每次组件渲染都会重新生成新的函数实例,导致useEffect的依赖项每次渲染都变动,触发react-hooks/exhaustive-deps规则校验失败。
  • 修复方法:将sendRequest函数移到useEffect回调内部,无需再将函数作为依赖项传入,依赖数组仅保留实际用到的外部变量showInfo和fighter即可。

报错2:组件卸载后更新状态告警

  • 报错原因:点击新游戏按钮时,showInfo状态变为false,FighterCardOverlay组件直接被卸载,但组件此前发起的接口请求仍在进行,请求完成后调用setUpdatedData更新已卸载组件的状态,触发内存泄漏警告。
  • 修复方法:
    • 在useEffect中新增AbortController控制器,请求时绑定signal参数,组件卸载时调用abort中断未完成的请求
    • 新增组件挂载状态标记,仅当组件仍处于挂载状态时才执行状态更新操作
    • 清理函数中额外重置状态,避免下次组件挂载时闪现旧数据

完整修复后的FighterCardOverlay组件代码

import { Hamster } from '../../models/Hamster';
import { useEffect, useState } from 'react';

interface CardGridProps {
    fighter: string;
    showInfo: boolean;
}

type Hamsters = Hamster;

const FighterCardOverlay = ({ fighter, showInfo }: CardGridProps) => {
    const [updatedData, setUpdatedData] = useState<Hamsters | null>(null);

    useEffect(() => {
        let isMounted = true;
        const controller = new AbortController();

        const sendRequest = async () => {
            try {
                const response = await fetch(`/hamsters/${fighter}`, {
                    signal: controller.signal
                });
                const data = await response.json();
                if (isMounted) {
                    setUpdatedData(data);
                }
            } catch (err) {
                if ((err as Error).name !== 'AbortError') {
                    console.error('请求仓鼠数据失败:', err);
                }
            }
        };

        if (showInfo) {
            sendRequest();
        }

        return () => {
            isMounted = false;
            controller.abort();
            setUpdatedData(null);
        };
    }, [showInfo, fighter]);

    return (
        <div className="fighterCardOverlay" >
           {updatedData ?
           <div>
            <li>Name: {updatedData.name}</li>
            <li>Age: {updatedData.age}</li>
            <li>Loves: {updatedData.loves}</li>
            <li>Favorite Food: {updatedData.favFood}</li>
            <li>Games: {updatedData.games}</li>
            <li>Wins: {updatedData.wins}</li>
            <li>Defeats: {updatedData.defeats}</li>
            </div>
            : 'Loading info...'
            }

        </div>
    )
}

export default FighterCardOverlay

额外说明

不需要修改父组件Game的代码,替换FighterCardOverlay组件后即可消除所有控制台报错,原有游戏逻辑完全不受影响。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.23 17:06:04