【问题标题】:Avoid update on an unmounted component避免更新未安装的组件
【发布时间】:2021-04-07 18:39:26
【问题描述】:

我阅读了很多类似的问题,但我的问题似乎有些不同。
我正在尝试登录,但出现以下错误。

警告:无法对未安装的组件执行 React 状态更新。 这是一个空操作,但它表明您的应用程序中存在内存泄漏。 要修复,请取消 useEffect 中的所有订阅和异步任务 清理功能。

我附上了处理所有逻辑的 AuthContext.js,希望你能解释我哪里出了问题,以及它表明我需要学习什么知识。

import React, { useContext, useState } from 'react'
import {postData} from '../adapters/authAdapter';

const AuthContext = React.createContext();

export function useAuth() {
    return useContext(AuthContext);
}

export function AuthProvider({children}) {
    const [currentUser,setCurrentUser] = useState(null);

    async function login(email,password) {
        const adaptedRes = await postData('log-in',{email,password});
        if(adaptedRes.err) {
        throw new Error(adaptedRes.message)
        } else {
        return setCurrentUser(adaptedRes.data);
        }
    }

    const value = {
        currentUser,
        login
    };

    return (
        <AuthContext.Provider value={value}>
            {children}
        </AuthContext.Provider>
    )
}

提前谢谢你

【问题讨论】:

  • 你能解释一下我需要在哪里实现哪个钩子吗?
  • 该错误意味着您的setCurrentUser() 函数正在被调用,而AuthProvider 未当前安装。这就是为什么,使用useRef() 检查您的AuthProvider 是否已安装,然后按照链接中的说明设置状态
  • 但我从 AuthProvider 中调用异步函数。每个答案都像 useEffect(.. asyncFunction()...)
  • 问题正如其他人所说,AuthProvider 组件正在被卸载之前 setCurrentUser 被调用。与其使用创可贴修复来阻止状态更新,不如找出未安装身份验证提供程序的原因。这是您通常希望包装 整个 app 并始终安装的提供程序组件之一。我的猜测是,您已将该身份验证提供程序的范围缩小到仅围绕您的身份验证组件 UI,然后您在其他地方导航并且该提供程序不再可用。

标签: reactjs memory-leaks react-hooks fetch


【解决方案1】:

该错误表示您的setCurrentUser() 函数正在被调用,而AuthProvider 当前不是mounted。这就是为什么,使用useRef() 检查您的AuthProvider 是否为mounted,然后按照链接中的说明设置状态:

export function AuthProvider({children}) {
    const [currentUser,setCurrentUser] = useState(null);
    const isMounted = useRef(false);

    useEffect(() => {
        // Becomes true on component mount
        isMounted.current = true;
         
        // becomes false on unmount
        return () => {isMounted.current = false;}
    
    
    }, [])

    async function login(email,password) {
        const adaptedRes = await postData('log-in',{email,password});
        if(adaptedRes.err) {
        throw new Error(adaptedRes.message)
        } else {
            if(!isMounted.current) {
            // Check if component is mounted
            console.log('component is not mounted');
            return;
        }
        return setCurrentUser(adaptedRes.data);
        }
    }

    const value = {
        currentUser,
        login
    };

    return (
        <AuthContext.Provider value={value}>
            {children}
        </AuthContext.Provider>
    )
}

更新正如 Drew 指出的:

问题正如其他人所说,在调用 setCurrentUser 之前正在卸载 AuthProvider 组件。与其使用创可贴修复来阻止状态更新,不如找出未安装身份验证提供程序的原因。这是您通常希望包装整个应用程序并始终挂载的提供程序组件之一。我的猜测是,您已将该身份验证提供程序的范围缩小到仅围绕您的身份验证组件 UI,然后您在其他地方导航并且该提供程序不再可用。

所以,你也应该检查一下,如果你收到这个错误,那么某处存在实现问题。

【讨论】:

  • 有效!这是使用 ContextAPI 的常见问题还是我做得不对?这似乎是“不必要的”复杂性
  • @MarcosMolina 问题与 Context API 无关。这只是一个正常的 React 组件问题。请参阅我上面的评论。
  • 感谢德鲁指出这一点。我已经更新了答案,@MarcosMolina,如果您满意,请接受我的回答。
  • 如前所述,我将 AuthProvider 移至应用程序,但仍然出现错误。在 index.js 中。 ReactDOM.render( , document.getElementById('root') );
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-22
  • 2021-12-20
相关资源
最近更新 更多