当前位置: 首页 > 知识库问答 >
问题:

反应错误->错误:超过最大更新深度

包建义
2023-03-14

早上好,我正在开发一个React应用程序,通过REST API与后端通信。

该应用程序体系结构还使用 React 路由器,并使用服务器提供并存储在会话存储中的 JWT 令牌实现身份验证功能。

基本上:

  • 用户连接到应用程序
  • 如果用户未登录,则重定向到登录页面
  • 登录后,它会重定向到带有路径/entsorga/home的主页,其中应该显示带有路径/entsorga的组件和带有路径/entsorga/home的组件(如果一个很好地理解React路由器的工作)

在启动应用程序时,用户被正确重定向到登录页面,并可以正确进行身份验证,身份验证后,页面url以正确的方式更改,但组件不会呈现,并显示后续错误。

虽然我对React完全陌生,但我面临着错误:

Error: Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.

我知道错误来自一个函数连续调用setState的事实,我已经试图逐个消除对函数的调用,但这并不能解决问题,所以它不应该是关于我的一个函数。

React Router中是否有我可能错过的东西,它与组件生命周期钩子进行交互并使此错误发生?

指数tsx页面:

ReactDOM.render(
    <React.StrictMode>
        <BrowserRouter>
            <Route exact path='/'>
                {authenticationService.isUserAuthenticated() ? <Redirect to='/entsorgafin' /> : <Login />}
            </Route>
            <Route path='/entsorgafin'>
                {authenticationService.isUserAuthenticated() ? <Redirect to='/entsorga/home' /> : <Redirect to='/' />}
            </Route>
            <Switch>
                <Route path='/entsorga' component={Header} />
                <Route path='/entsorga/home' component={Homepage} />
            </Switch>
        </BrowserRouter>
    </React.StrictMode>,
    document.getElementById('root')
);

Header.tsx组件:

class Header
    extends Component<any, any>
{
    //costruttore
    constructor(props: any)
    {
        //props management
        super(props);
        
        //state management
        this.state = {
            anniAttivita: [],
            nomeProprietaGrafici: [],
            loggedIn: authenticationService.isUserAuthenticated
        }
        
        //methods binding
        this.getAnniAttivita = this.getAnniAttivita.bind(this);
        this.setProprietaCruscotto = this.setProprietaCruscotto.bind(this);
        this.logout = this.logout.bind(this);
    }
    
    //component lifecycle hook --> creation
    componentDidMount()
    {
        this.getAnniAttivita();
        this.setProprietaCruscotto();
    }
    
    //metodo per recuperare gli anni di attività dell'impianto
    getAnniAttivita()
    {
        utilityService.recuperaAnniAttivita().then(
            r =>
            {
                this.setState({anniAttivita: r.data})
            }
        );
    }
    
    //metodo per settare le proprietà disponibili all'interno del cruscotto
    setProprietaCruscotto()
    {
        let proprietaGrafici = [
            {
                beName: "caloPesoGiorno",
                feName: "Calo Peso Giornaliero"
            },
            {
                beName: "caloPeso",
                feName: "Calo Peso"
            },
            {
                beName: "temperaturaMateriale",
                feName: "Temperatura Materiale"
            },
            {
                beName: "temperaturaReattore",
                feName: "Temperatura Reattore"
            },
            {
                beName: "rhInterna",
                feName: "RH Interna"
            },
            {
                beName: "deltaP",
                feName: "Delta P"
            },
            {
                beName: "tempoLatenza55",
                feName: "Tempo Latenza 55"
            },
            {
                beName: "ph",
                feName: "PH"
            },
            {
                beName: "rh",
                feName: "RH"
            },
            {
                beName: "germinazione",
                feName: "Germinazione"
            },
            {
                beName: "inerti_litoidi",
                feName: "Inerti Litoidi"
            },
            {
                beName: "plastiche_vetri_metalli",
                feName: "Plastiche, Vetri, Metalli"
            }
        ]
        
        this.setState({nomeProprietaGrafici: proprietaGrafici});
    }
    
    //effettua il logout
    logout()
    {
        authenticationService.logout();
        this.setState({loggedIn: false});
    }
    
    //metodo che effettua il render del componente
    render()
    {
        if (this.state.loggedIn)
        {
            return (
                <Redirect to='/' />
            );
        }
        
        return (
            <nav className="navbar navbar-light sticky-top navbar-expand-xl py-0 pl-0">
                <Link className="navbar-brand py-0" to={"/entsorgafin/home"}>
                    <img src={logo} className="img-fluid d-inline-block align-top" alt="EntsorgaFin logo" />
                </Link>
                <button className="navbar-toggler" type="button" data-toggle="collapse"
                        data-target="#navbarSupportedContent"
                        aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
                    <span className="navbar-toggler-icon" />
                </button>
                
                <div className="collapse navbar-collapse" id="navbarSupportedContent">
                    <ul className="navbar-nav mr-auto">
                        <li className="nav-item dropdown with-right-border">
                            <Link className="nav-link dropdown-toggle text-dark" to="#"
                                  id="tracciabilitaLottiNavbarDropdown"
                                  role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                                DOCUMENTO TRACCIABILIT&Aacute; LOTTI
                            </Link>
                            <div className="dropdown-menu" aria-labelledby="tracciabilitaLottiNavbarDropdown">
                                {
                                    //creazione di un link per ogni anno di attività
                                    this.state.anniAttivita.map(
                                        (anno: number) =>
                                        {
                                            return (
                                                <Fragment>
                                                    <Link key={anno} className="dropdown-item text-center"
                                                          to={"/entsorgafin/tracciabilitaLotti"}>{anno}</Link>
                                                    <div className="dropdown-divider custom-dropdown-divider" />
                                                </Fragment>
                                            );
                                        }
                                    )
                                }
                            </div>
                        </li>
                        <li className="nav-item dropdown with-right-border">
                            <Link className="nav-link dropdown-toggle text-dark" to="#"
                                  id="performanceImpiantoNavbarDropdown" role="button" data-toggle="dropdown"
                                  aria-haspopup="true" aria-expanded="false">
                                PERFORMANCE D'IMPIANTO
                            </Link>
                            <div className="dropdown-menu" aria-labelledby="performanceImpiantoNavbarDropdown">
                                {
                                    //creazione di un link per ogni anno di attività
                                    this.state.anniAttivita.map(
                                        (anno: number) =>
                                        {
                                            return (
                                                <Fragment>
                                                    <Link key={anno} className="dropdown-item text-center"
                                                          to={"/entsorgafin/performanceImpianto"}>{anno}</Link>
                                                    <div className="dropdown-divider custom-dropdown-divider" />
                                                </Fragment>
                                            );
                                        }
                                    )
                                }
                            </div>
                        </li>
                        <li className="nav-item dropdown">
                            <Link className="nav-link dropdown-toggle text-dark" to="#"
                                  id="cruscottoCompletoNavbarDropdown"
                                  role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                                CRUSCOTTO COMPLETO
                            </Link>
                            <div className="dropdown-menu" aria-labelledby="cruscottoCompletoNavbarDropdown">
                                {
                                    //creazione di un link per ogni nome di proprietà disponibile
                                    this.state.nomeProprietaGrafici.map(
                                        (beName: string,
                                         feName: string) =>
                                        {
                                            return (
                                                <Fragment>
                                                    <Link key={beName}
                                                          className="dropdown-item text-center"
                                                          to={"/entsorgafin/performanceImpianto"}>${feName}</Link>
                                                    <div className="dropdown-divider" />
                                                </Fragment>
                                            );
                                        }
                                    )
                                }
                            </div>
                        </li>
                    </ul>
                    {/*<ul className="nav navbar-nav float-right-element">*/}
                    {/*<li>*/}
                    {/*    /!*<h6 className="no-margin vertical-align-text mr-1">Utente attivo:*!/*/}
                    {/*    /!*                                                   ${authenticationService.getCurrentUserName()} </h6>*!/*/}
                    {/*</li>*/}
                    {/*<li>*/}
                    {/*<button className="btn btn-sm btn-dark" onChange={this.logout}>Logout</button>*/}
                    {/*</li>*/}
                    {/*</ul>*/}
                </div>
            </nav>
        );
    }
}

export default Header;

Login.tsx组件:

class Login
    extends Component<any, any>
{
    //costruttore
    constructor(props: any)
    {
        //props management
        super(props);
        
        //state management
        this.state = {
            username: '',
            password: '',
            loggedIn: authenticationService.isUserAuthenticated()
        }
        
        //methods binding
        this.handleLogin = this.handleLogin.bind(this);
        this.onChangeUserName = this.onChangeUserName.bind(this);
        this.onChangePassword = this.onChangePassword.bind(this);
    }
    
    onChangeUserName(e: any)
    {
        this.setState({
            username: e.target.value
        });
    }
    
    onChangePassword(e: any)
    {
        this.setState({
            password: e.target.value
        });
    }
    
    handleLogin(e: any)
    {
        e.preventDefault();
        
        authenticationService.authenticate(this.state.username, this.state.password).then(
            () =>
            {
                this.setState({loggedIn: true});
            }
        );
    }
    
    render()
    {
        if (this.state.loggedIn)
        {
            return (
                <Redirect push to='/entsorga/home' />
            );
        }
        
        return (
            <div className="col-md-12">
                <div className="card">
                    Carta
                </div>
                <form onSubmit={this.handleLogin}>
                    <div className="form-group">
                        <label htmlFor="username">Nome Utente</label>
                        <input type="text" className="form-control" name="username" value={this.state.username}
                               onChange={this.onChangeUserName} required={true} />
                    </div>
                    <div className="form-group">
                        <label htmlFor="password">Password</label>
                        <input type="password" className="form-control" name="password" value={this.state.password}
                               onChange={this.onChangePassword} required={true} />
                    </div>
                    <div className="form-group">
                        <button className="btn btn-primary btn-block" type="submit" value="submit">
                            Login
                        </button>
                    </div>
                </form>
            </div>
        );
    }
}

export default Login;

主页仅打印带有H1标题的“主页”。

编辑

我编辑了索引。tsx类:

    <Switch>
        <Route exact path='/'>
            {authenticationService.isUserAuthenticated() ? <Redirect to='/entsorga/home' /> : <Login />}
        </Route>
        <Route path='/entsorga' component={Header} />
        <Route path='/entsorga/home' component={Homepage} />
        <Route path='/entsorga/tracciabilitaLotti' component={tracciabilitaLotti} />
        <Route path='/entsorga/performanceImpianto' component={performanceImpianto} />
        <Route path='/entsorga/graficiCruscotto' component={graficiCruscotto} />
    </Switch>

但是问题并没有解决,重定向的地方是:

>

  • 在 index.tsx 文件中,如果用户未登录,则将其重定向到主页或以其他方式重定向到主页

         <Route exact path='/'>
             {authenticationService.isUserAuthenticated() ? <Redirect to='/entsorga/home' /> : <Login />}
         </Route>
    

    在登录成功时重定向到主页的login.tsx文件中:

    if(this . state . logged in){ return(Redirect push to = '/ents orga/home ');}

    header.tsx 文件,在用户未登录的情况下重定向到 / (以防止在用户未登录的情况下看到该页面)

    if(this.state.loggedIn){return(重定向到='/');}

    < code>loggedIn状态由调用服务的helper函数在组件的构造函数中给出,我确信身份验证是成功的,因为我可以在日志中打印身份验证令牌。

    Header.tsx组件应该在所有页面上都被取消支付,这就是为什么我把它放在路径/entsorga中,所有其他组件都在/entsorga/**。

    编辑2

    服务器日志中,我可以看到来自React的多个请求(比需要的请求多得多),就好像Header.tsx组件在不断地重新呈现一样:我看到一个组件在其状态被修改时自动重新呈现,在Header组件中,状态在构造函数中被修改,并且在执行注销(尚未使用)时,setProprietaCruscotto(仅使用过一次)和getAnniAttivita,这可能是不断重新加载的原因。

    getAnniAttivita函数通过Axios调用API从服务器获取一些数据,服务器响应401(目前应该是这样),Axios可能是持续重新加载的原因吗?也许在错误之后,Axios会重试,直到调用成功,使状态多次改变?

  • 共有1个答案

    章飞章
    2023-03-14
    <Route exact path='/'>
         {authenticationService.isUserAuthenticated() ? <Redirect to='/entsorgafin' /> : <Login />}
     </Route>
    <Route path='/entsorgafin'>
        {authenticationService.isUserAuthenticated() ? <Redirect to='/entsorga/home' /> : <Redirect to='/' />}
    </Route>
    

    这两条路由总是被渲染,因为它们没有被包装在交换机中。

    现在,您在两条路由中都有重定向,并且在isUserAuthenticated结果的相反一侧。

    现在发生的是,你的应用程序在循环中被重定向,因为如果用户登录,将调用来自< code>entsorgafin的重定向,或者来自< code>/路径的重定向。

    您需要将这些添加到开关中,现在只会呈现第一页。

     类似资料:
    • 我有这个错误:错误:超过最大更新深度。当组件重复调用componentWillUpdate或componentDidUpdate内部的setState时,会发生这种情况。React限制嵌套更新的数量,以防止无限循环。 但是我不明白怎么解决!我只是在发布我的代码,对不起… 我的代码:

    • 我试图在参数更改时映射我的 redux 数组。它按预期呈现,但我在控制台中收到此错误。尝试了一些对useeffect的依赖性,但无法修复它。不知道为什么会发生这种情况。感谢您的帮助。 错误; 超过最大更新深度。当组件在useEffect中调用setState时,可能会发生这种情况,但useEfect要么没有依赖项数组,要么在每次渲染时都会更改其中一个依赖项。 我的代码;

    • 我正在用React做我的前几个实验,在这个组件中,我调用了一个外部API来获取所有NBA玩家的列表,通过作为组件道具接收的teamId过滤它们,最后呈现过滤玩家的标记。 一个需要考虑的问题是,由于我调用了API并获得了一个大列表,所以我将它保持在组件的状态,以便对该组件的新调用将使用该状态,而不是再次调用API。这不是生产代码,我没有API,所以我这样做是因为我收到了“太多请求”消息,因为我一直在

    • 我目前收到Maxiumum更新深度错误,不知道为什么。在我的代码中看不到无限循环。 "超过了最大更新深度。当组件在useEffect内部调用setState时,可能会发生这种情况,但useEffect要么没有依赖关系数组,要么其中一个依赖关系在每次渲染时都会发生变化。 此处显示错误 ReactJS组件代码: 下面的代码似乎有错误:超过了最大更新深度。当组件在useEffect中调用setState

    • 我正在尝试使用master中的一些函数。js组件。当我运行下面的代码时,我得到错误“error:Maximum update depth exceeded。当组件在componentWillUpdate或componentDidUpdate.React中重复调用setState时,可能会发生这种情况。React限制嵌套更新的数量,以防出现无限循环。” 我在孙子组件中添加按钮时出错了。 如果我注释掉

    • 当我运行我的代码时,我收到了这个错误。 超过了最大更新深度。当组件重复调用组件WillUpdate或组件DidUpdate中的setState时,可能会发生这种情况。React限制嵌套更新的数量以防止无限循环。 这是代码。它在引用。 我按照React网站上的文章所说的方式设置了我的东西,它“来了”于这个简洁的控制台类型,这就是我产生上述代码的地方。我对React、JSX和Javascript(以及