Reactjs 使用 setTimeout 创建无限循环

Reactjs creates infinite loop using setTimeout

这是我的 App.js,其中包含 Header 和 MainView 一个警报对话框。警报对话框有两个状态控制的道具:

msg={alertMsg} toggleClass={alertToggleClass}

AlertDialog 的任务是显示类名是否为“alertDlg”,如果是“alertDlg alertDlgClosed”则消失。通过检查器手动测试(更改类名)表明它工作正常。

因此alertToggleClass在初始化时设置为“alertDlg alertDlgClosed”,默认情况下隐藏警告对话框。

在 MainView 组件中(在 render() 之前) sendGlobalAlert("Test Alert Msg") 被调用,这只是对 App.js 中 showAlert(msg) 方法的回调。

现在是棘手的部分:在 showAlert(msg) 方法中调用 setAlertToggleClass("alertDlg"); 会按预期显示自定义警报对话框。然而,试图通过在 setTimeout 中调用 setAlertToggleClass("alertDlg alertDlgClosed"); 来禁用它会创建一个无限循环到 showAlert(msg)-method.

据我所知,setTimeout(...) 中没有递归。

我无法解释这种行为,如果有任何有用的提示,我将不胜感激。

import './App.css';
import AlertDialog from './components/general/alert-dialog/AlertDialog';
import { Header } from './components/general/Header';
import MainView from './components/main/MainView';
import { useState } from "react";

function App() {
    const [alertMsg,setAlertMsg] = useState(""); 
    const [alertToggleClass,setAlertToggleClass] = useState("alertDlg alertDlgClosed"); 

    function showAlert(msg){
        console.log("Showing alert dialog");
        setAlertMsg(msg); // set message
        setAlertToggleClass("alertDlg"); // show alert dialog
        
        setTimeout(function() {
            if(alertToggleClass === "alertDlg" ){
                setAlertToggleClass("alertDlg alertDlgClosed");
                console.log("hide alert");
            }
            // setAlertToggleClass("alertDlg test");
        },3500);
    }
    return (
        <div className="container">
            <Header/>
            <MainView sendGlobalAlert={showAlert}/>
            <AlertDialog msg={alertMsg} toggleClass={alertToggleClass} />
        </div>
    );
}

export default App;

MainView 中的 sendGlobalAlert("Test Alert Msg"); 是这里的问题。

在这个调用之后,基本上是对 App.js 的 showAlert(msg) 方法的回调,AlertDialog 使用的存储在状态中的道具被改变了。由于对这些道具的更新,AlertDialog 重新呈现并再次导致 App.js 中的重新呈现,这意味着它的元素也必须重新呈现。由于它包括 MainView,App.js 的重新渲染意味着 MainView 的重新渲染,它调用 sendGlobalAlert("Test Alert Msg"); 并开始递归。

主视图是这样的:

const MainView = ({sendGlobalAlert}) => {
    sendGlobalAlert("Test Alert Msg");
    return (
        <div className="main-view" >
            <BillView/>
            <InteractionView sendGlobalAlert={sendGlobalAlert}/>
        </div>
    )
}