【问题标题】:Reactjs creates infinite loop using setTimeoutReactjs 使用 setTimeout 创建无限循环
【发布时间】:2021-12-11 01:49:41
【问题描述】:

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

msg={alertMsg} toggleClass={alertToggleClass}

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

因此在初始化的时候alertToggleClass设置为“alertDlg alertDlgClosed”,这样alert对话框默认是隐藏的。

在 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;

【问题讨论】:

  • 您是否介意制作一个可以显示完整代码的沙盒。如果您愿意,可以使用 codesandbox.io 。这将更容易理解究竟是什么问题。
  • 最好将问题中的代码作为minimal reproducible example 而不是外部沙箱。见How do I create a React Stack Snippet with JSX support?。也就是说——setAlertToggleClass("alertDlg") 是异步的并会触发重新渲染,因此您可能希望在此处使用 ref,而不是尝试在 setTimeout 中读取 alertToggleClass
  • 我想我知道问题出在哪里了...被调用立即在 MainView 中,这就是它不断重新渲染的原因。将持续时间从 3500 减少到 100 有助于对它的限制做出反应,导致错误:“重新渲染太多。React 限制渲染数量以防止无限循环。”。将用相应的答案更新问题。

标签: javascript reactjs settimeout


【解决方案1】:

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

在此调用之后,基本上是对 App.js 的 showAlert(msg) 方法的回调,AlertDialog 使用的存储在 state 中的 props 发生了变化。由于这些道具的更新,AlertDialog 重新渲染,这再次导致 App.js 中的重新渲染,这意味着它的元素也必须重新渲染。由于包含了MainView,所以App.js的重新渲染意味着MainView的重新渲染,调用sendGlobalAlert("Test Alert Msg");并开始递归。

这是 MainView 的样子:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-24
    • 1970-01-01
    • 1970-01-01
    • 2021-02-20
    • 2020-02-24
    • 2016-10-22
    相关资源
    最近更新 更多