【问题标题】:Can't perform a React state update on an unmounted component.(UseEffect)(Context API)(REACT.js)无法对未安装的组件执行 React 状态更新。(UseEffect)(Context API)(REACT.js)
【发布时间】:2020-10-09 07:36:09
【问题描述】:

所以我收到了这个警告:-

*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)*

好吧,当我重新路由到产品编辑组件时,它发生在产品组件中! Products 组件用于列出所有产品,product edit 用于编辑产品详细信息,这两个组件都使用 useContext 连接到相同的上下文 API。 我的上下文 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,loading , 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();
 }, [])
...........

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

Error message Details and console log?

【问题讨论】:

    标签: reactjs firebase google-cloud-firestore react-context use-context


    【解决方案1】:

    这个问题与 Firestore 无关,而这似乎是 react 的一个常见问题。

    • 如果组件还没有挂载,我们就不需要在回调中更新状态。

    • 在更新状态之前最好在异步函数中添加一个 if 块来检查

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

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

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

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

    希望我正确理解了这个问题,并且建议对您有所帮助!

    【讨论】:

      【解决方案2】:

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

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

      但这不是正确的,你应该做的是在组件卸载时取消你的 API 请求,我对使用 axios 时的请求取消知之甚少。您应该在网上搜索有关 Firebase 中的 API 请求取消或您正在使用的任何内容,因为如果您没有在组件卸载时更新您的反应状态,那么 API 请求仍然会继续在后台运行,这是主要问题,这就是为什么反应会抛出这个警告。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-01-18
        • 2019-07-24
        • 2021-12-03
        • 2021-09-28
        • 2020-07-19
        • 2020-08-02
        • 2021-07-01
        • 2020-11-21
        相关资源
        最近更新 更多