无法对已卸载的组件执行React状态更新UseEffectContext APIREACT.js

问题描述

所以我收到此警告:-

*Can't perform a React state update on an unmounted component. This is a no-op,but it indicates a memory leak in your application. To fix,cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.
    in Products (created by Context.Consumer)*

好吧,当我重新路由到“产品编辑”组件时,它出现在“产品”组件中! 产品组件用于列出所有产品,产品编辑用于编辑产品详细信息,并且这两个组件都使用useContext连接到相同的上下文API。 我的Context API提供程序看起来像这样

*import React,{ useState,createContext,useEffect} from 'react';
import firebase from "../firebase";

export const ProdContext = createContext();

const ProdContextProvider = props => {
    const [products,setproducts]= useState([])
    const [loading,setloading] = useState(true)
    const [subcribe,setsubcribe] = useState(false)


    const unsub =()=>{
        setsubcribe(false);
        console.log("unsubcribe--"+subcribe)
      }
      const sub =()=>{
        setsubcribe(true);
        console.log("subcribe--"+subcribe)
      }

    useEffect(() => {
        let mounted = true;
        setloading(true)
        async function fetchData() {
        setloading(true);
        await firebase.firestore()
        .collection("products")
        .onSnapshot((snapshot)=>{
            
            const data = snapshot.docs.map((doc)=>(
                {
                    id : doc.id,...doc.data()
                }
            ))
            console.log("b4 if--"+subcribe)
            if(subcribe){
                console.log("in if--"+subcribe)
            setproducts(data)
            setloading(false)
            }
        })
        }
        fetchData();
        return () => mounted = false;
    },[subcribe])
    
    console.log("after getting bottom"+subcribe)
    return (
        <ProdContext.Provider value={{subcribe:subcribe,prodloading:loading,products: products,loading:loading,sub:sub,unsub:unsub}}>
            {props.children}
        </ProdContext.Provider>
    );
}
export default ProdContextProvider;*

我的产品组件看起来像这样:

export default function Products(props){
    const {products,loading,sub,unsub,subcribe}= useContext(ProdContext)
    const [selectid,setselectid] = useState("")
    const [ShowLoading,setShowLoading] = useState(true);
    const [showAlert2,setShowAlert2] = useState(false);
    const [redirect,setredirect] = useState(false)
    const [value,setValue] = useState(null);
    const [inputValue,setInputValue] = useState('');

    
 useEffect(() => {
     sub();
     console.log("product mound--"+subcribe)
 },[])

 useEffect(() => {
    return () => {
        console.log("product unsub--"+subcribe)
        unsub();
        console.log("product unmound--"+subcribe)
    };
  },[]);

      if (redirect) {
        return <Redirect push to={{
            pathname: `/products/${selectid}`,}} />;
      }
    return ( .........)}

产品编辑组件:

const Productedit = (props) => {

const {products,subcribe} = useContext(ProdContext);
const { sub,unsub } = useContext(ProdContext);
  const [formData,setformData] = useState({});
  const {category} = useContext(CatContext)
  const [showLoading,setShowLoading] = useState(false);
  const [mainurl,setmainurl] = useState(null);
  const [imggal,setimggal] = useState([]);
  const [situation,setsituation] = useState("")
  const [redirect,setredirect] = useState(false)
  const [showAlert,setShowAlert] = useState(false);
  const [msg,setmsg] = useState(true);

 useEffect(() => {
     sub();
     console.log("productedit mound--"+subcribe)
     return () => unsub();
 },[])
...........

好吧,我认为问题在于即使卸载了产品组件,它仍然仍订阅了getproduct provider,但我无法解决任何人都可以提供帮助的问题

Error message Details and console log

解决方法

该问题与Firestore无关,但这似乎是react的常见问题。

  • 如果该组件尚未安装,我们就不需要更新回调中的状态。

  • 最好在更新状态之前进行检查,方法是在异步函数中添加if块

    if(mounted) {// Code inside the async tasks}

有关此警告的更多信息,请参见此处[1]。

[1] https://www.debuggr.io/react-update-unmounted-component/#state-updates

(这应该是一条评论,因为我没有足够的声誉,因此发布为答案)

希望我理解正确的问题,该建议会有所帮助!

,

除了仅初始化 mounted 外,您没有使用它,如果卸载了组件,则不应更新您的反应状态。成功的API请求后,您应该在回调中执行此操作:

if(mounted){
   // your state update goes here
}

但这不是正确的,您应该做的是在卸载组件时取消API请求,我不太了解使用 axios 时的请求取消。您应该在网络上搜索有关Firebase中API请求取消的信息,或者您正在使用的内容,因为如果组件卸载后您没有更新React状态,那么API请求仍然在后台运行,这是主要问题,这就是为什么React会抛出此错误警告。