问题描述
所以我收到此警告:-
*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会抛出此错误警告。