You need to enable JavaScript to run this app. React TS项目出现「无法对已卸载组件执行state更新」警告怎么解决
优惠活动
大模型
产品
解决方案
定价
更多

React TS项目出现「无法对已卸载组件执行state更新」警告怎么解决

问题根因

这个警告触发的核心原因是:你的MyModal和UpdateForm组件中存在未做取消/挂载判断的异步请求,在两种场景下会触发卸载组件的状态更新:

  • 用户触发更新/删除书籍的请求后,不等接口返回就手动关闭了Modal,此时两个组件已经卸载,接口返回后执行setError/setReload等状态更新操作就会触发警告
  • 接口返回后你先执行了状态更新,再触发window.location.reload()刷新页面,刷新过程中组件开始卸载,刚触发的状态更新就命中了规则

修复方案

方案1:最简修复(保留现有刷新逻辑)

给两个组件增加挂载状态标记,所有状态更新前先判断组件是否仍处于挂载状态:

UpdateForm.tsx 修改示例

import { useState, SyntheticEvent, useRef, useEffect } from "react";

const UpdateForm = (props: {bookId: string, setReload: (reload: boolean) => void}) => {
    const [bookStatus, setBookStatus] = useState('reading')
    const [error, setError] = useState(<></>)
    const bookId = props.bookId
    // 新增挂载标记
    const isMounted = useRef(true)
    useEffect(() => {
        return () => {
            isMounted.current = false
        }
    }, [])

    const submit = async (e: SyntheticEvent) => {
        e.preventDefault();

        if (window.confirm(`Do you want to move this book to ${bookStatus}?`)) {
            const response = await fetch(`${process.env.REACT_APP_API_BASE_URL}/books/updatestatus`, {
                method: 'POST',
                headers: {'Content-Type': 'application/json'},
                credentials: 'include',
                body: JSON.stringify({
                    "status": bookStatus,
                    "id": bookId
                })
            });

            const content = await response.json();
            // 所有状态更新前先判断是否挂载
            if (!isMounted.current) return
            console.log(bookStatus)

            if (content.status !== 200) {
                setError((
                    <div className="alert alert-danger" role="alert">
                        {content.message}
                    </div>
                ))
            } else {
                setError((
                    <div className="alert alert-success" role="alert">
                        {content.message}
                    </div>
                ))
                props.setReload(true)
            }
        }
    }
    // 其余渲染代码保持不变
}

MyModal.tsx 同理增加相同的isMounted逻辑即可。


方案2:更优体验修复(推荐)

你已经使用了react-query管理数据,完全可以不用window.location.reload()这种全页刷新的方案,替换为刷新react-query缓存即可,体验更好也能避免该问题:

  1. 移除MyModal中的reload状态和handleClose中的刷新逻辑
  2. 操作成功后调用invalidateQueries刷新书籍列表:
// MyModal.tsx 中先导入依赖
import { useQueryClient } from 'react-query'

const MyModal = (props: {show: boolean, book: BookType, setShow: (status: boolean) => void }) => {
    const queryClient = useQueryClient()
    const [error, setError] = useState(<></>)
    // 移除reload相关状态定义
    const bookId = props.book.id
    const bookName = props.book.name
    
    const handleClose = () => {
      props.setShow(false);
    }

    const deleteBook = async (e: SyntheticEvent) => {
      e.preventDefault()
      if (window.confirm("Are you sure?")) {
        const response = await fetch(`${process.env.REACT_APP_API_BASE_URL}/books/deletebook`, {
            method: 'POST',
            headers: {'Content-Type': 'application/json'},
            credentials: 'include',
            body: JSON.stringify({
                "id": bookId,
                "name": bookName
            })
        });
        const content = await response.json();
        if (content.status !== 200) {
            setError((
                <div className="alert alert-danger" role="alert">
                    {content.message}
                </div>
            ))
        } else {
            setError((
                <div className="alert alert-warning" role="alert">
                    {content.message}
                </div>
            ))
            // 刷新books缓存,列表自动更新无需刷新页面
            queryClient.invalidateQueries('books')
            // 操作成功后延迟关闭弹窗,让用户看到成功提示
            setTimeout(() => props.setShow(false), 1000)
        }
      }
    }
    // 其余渲染代码保持不变,UpdateForm同理替换setReload为invalidateQueries逻辑即可
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.14 19:15:02