簡體   English   中英

在 useEffect 中不使用異步效果時,無法對未安裝的組件執行 React 狀態更新

[英]Can't perform a React state update on an unmounted component, when using no async effects in useEffect

我的 React 應用程序出現錯誤。

警告:無法對卸載的組件執行 React 狀態更新。 這是一個空操作,但它表明您的應用程序中存在內存泄漏。 要修復,請取消 useEffect 清理函數中的所有訂閱和異步任務。

在 LayoutLogin(在 AppContent.js:22)

在路由中(在 AppContent.js:22)

據我所知,這是因為組件LayoutLogin在看到您已通過身份驗證並將您重定向到您應該訪問的頁面后就會被卸載。 但我不知道如何修復它,因為我沒有看到任何異步函數被調用,這就是我一直在搜索的所有內容都被用作如何修復的示例。 那么我應該如何阻止這種內存泄漏呢?

AppContent.js

export default function AppContent() {
    const [settings] = useGlobal('settings');

    return (
        <Switch>
            {settings.guestEnabled && <Route exact path="/"><LayoutDash/></Route>}
            {!settings.guestEnabled && <PrivateRoute exact path="/"><LayoutDash/></PrivateRoute>}
            {settings.registrationEnabled && <Route exact path="/register"><LayoutRegister/></Route>}
            <PrivateRoute path="/options"><LayoutOptions/></PrivateRoute>
            <PrivateRoute path="/settings"><LayoutSettings/></PrivateRoute>
            <Route exact path="/login"><LayoutLogin/></Route>  // Line 22
        </Switch>
    );
}

LayoutLogin.js

import React, {useEffect} from 'react';
import LayoutBase from "./LayoutBase";
import {useDispatch, useGlobal} from 'reactn';
import {useAPI} from "../hooks/useAPI";
import {useHistory, useLocation} from "react-router-dom";

export default function LayoutLogin() {
    const classes = useStyles();
    const [isAuthenticated] = useGlobal('isAuthenticated');
    const [options] = useGlobal('options');
    const authError = useDispatch('authError');
    const authSuccess = useDispatch('authSuccess');
    const fetchToken = useAPI('/api/auth/token/obtain/');


    const [login, setLogin] = React.useState({
        username: '',
        password: '',
    });
    const [loading, setLoading] = React.useState(false);
    const [error, setError] = React.useState(false);

    const history = useHistory();
    const location = useLocation();
    let { from } = location.state || { from: { pathname: "/" } };

    useEffect(() => {
        document.title = `Login | ${options.appName}`;
        if (isAuthenticated) {
            history.replace(from);
        }
    }, [isAuthenticated, options]);

    // Handle state change from form elements
    const handleLoginChange = option => event => {
        setLogin({
            ...login,
            [option]: event.target.value,
        });
    };

    const handleSubmit = () => {
        // submit form here
    };

    return (
        <LayoutBase>
            // Login form components here
        </LayoutBase>
    );
}

我懷疑這與 LayoutLogin 關系不大,而與 AppContent 中路由的條件渲染有關。 您提供的代碼中似乎沒有卸載 LayoutLogin。 AFAIK,如果一個元素是另一個無條件元素的無條件子元素,React 不會卸載它。 它可能不會被要求重新渲染,但它仍然在樹中。

然而,頂級 Route 和 PrivateRoute 對象是有條件地呈現的,並且當這些條件為真/假時將掛載/卸載。 我以前從未見過這種模式,感覺像是一種反模式。 通常定義路由,然后它們的內容根據內容可用的狀態決定它們是否應該呈現有效結果或錯誤。

我能看到 LayoutLogin 導致問題的唯一方法是它的一個鈎子沒有在它自己之后清理。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM