【问题标题】:ReactJs Maximum update depth exceededReactJs 超过最大更新深度
【发布时间】: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" alt="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

标签: reactjs typescript


【解决方案1】:

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

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

【讨论】:

  • 不知道 bisect,谢谢。其他组件中的问题实际上是一些导致上述错误的 setState/render 循环吗?
  • @ford04 错误的行导致重定向回 LoginComponent 进而重定向回具有错误行的组件等。基本上是一个来回调用&lt;redirect ...&gt; 的条件。
猜你喜欢
  • 1970-01-01
  • 2019-10-23
  • 2020-07-15
  • 1970-01-01
  • 2021-07-12
  • 2019-04-03
  • 2019-02-14
  • 2019-07-17
相关资源
最近更新 更多