ReactJs 超过最大更新深度

Posted

技术标签:

【中文标题】ReactJs 超过最大更新深度【英文标题】:ReactJs Maximum update depth exceeded 【发布时间】:2020-01-04 19:24:16 【问题描述】:

我正在尝试实现登录视图,但不断出现错误:

已超过最大更新深度。这可能发生在组件 在 componentWillUpdate 内重复调用 setState 或 组件更新。 React 将嵌套更新的数量限制为 防止无限循环。

点击提交按钮时。

import './LoginView.css'
import React,  useState  from 'react'
import  Button, TextField, CircularProgress  from '@material-ui/core'
import Auth from '../../utils/Auth'
import  Redirect  from 'react-router-dom'
import Network from '../../utils/Network'
import Toast,  IToastData, ToastType  from '../Toast/Toast'
import AdManager from '../../utils/AdManager'
import pkg from '../../../package.json'
import Logo from "../../assets/logo.png"

export default function LoginView() 
    const [username, setUsername] = useState('')
    const [password, setPassword] = useState('')
    const [isLoading, setIsLoading] = useState(false)
    const [toastData, setToastData] = useState<IToastData | undefined>(undefined)

    const onSubmit = async () => 
        try 
            setIsLoading(true)
            await Network.instance.login(username, password)
            const success = Auth.instance.isLoggedIn()
            if (success) 
                await AdManager.instance.start()
            
         catch (error) 
            setToastData(
                type: ToastType.Error,
                message: "Something went wrong!"
            )
         finally 
            setIsLoading(false) // According to react this is the culprit
        
    

    const createInputFields = () => 
        return (
            <>
                <TextField
                    className="textField"
                    label="Username"
                    type="email"
                    margin="normal"
                    onChange=x => setUsername(x.target.value)
                    required=true
                />
                <TextField
                    className="textField"
                    label="Password"
                    type="password"
                    margin="normal"
                    onChange=x => setPassword(x.target.value)
                    required=true
                />
            </>
        )
    

    if (Auth.instance.isLoggedIn()) 
        const path = (AdManager.instance.sources.length === 1) ? '/' : '/selection'
        return <Redirect to=path />
    
    return (
        <>
            <div className="root">
                <img src=Logo className="Logo"  />
                <div className="TextFieldsContainer">
                    isLoading ? <CircularProgress /> : createInputFields()
                </div>
                <Button className="button" variant="contained" component="span" disabled=isLoading || (!username || !password) onClick=onSubmit>
                    Log in
                </Button>
                !!toastData && <Toast open=true message=toastData.message type=toastData.type />
            </div>
            <div className="VersionNumber">pkg.version</div>
        </>
    )

【问题讨论】:

setState 是异步操作。所以你应该把try ... 放在setState 的回调中。把它们锁起来。 捕获后使用finally 如果 setState 你的意思是 onSubmit,那么它已经是异步的了。我最后加了(谢谢),但结果是一样的。 您可以将其发布为答案以帮助未来的读者。此错误消息似乎并不少见。 同意 ford04 【参考方案1】:

我已经解决了这个问题,虽然错误是由 React 抱怨的指定行间接调用的;实际原因是重定向到的组件中的一行代码。

总结一下。 React 在其错误消息中是正确的,但不够具体,无法提供任何实际帮助。我使用git bisect 发现了错误。经常提交并确定提交范围是这里的救星。

【讨论】:

不知道 bisect,谢谢。其他组件中的问题实际上是一些导致上述错误的 setState/render 循环吗? @ford04 错误的行导致重定向回 LoginComponent 进而重定向回具有错误行的组件等。基本上是一个来回调用&lt;redirect ...&gt; 的条件。

以上是关于ReactJs 超过最大更新深度的主要内容,如果未能解决你的问题,请参考以下文章

超过最大更新深度 - React Js

ReactJs抛出最大更新深度错误

超过最大更新深度。当组件在 componentWillUpdate 中重复调用 setState 时,可能会发生这种情况

react的最大更新深度是多少?

reactjs - 导入 3 级深度反应

ReactJS - 如何将“全局”数据传递给深度嵌套的子组件?