我们应该使用 firebase 中 Auth.onAuthStateChanged() 返回的取消订阅方法来清理内存泄漏吗?
Should we be using the unsubscribe method returned by Auth.onAuthStateChanged() in firebase to clean up memoery leaks?
这是我的代码:
import React, {useState, useRef, useEffect} from 'react';
import { getAuth, onAuthStateChanged } from 'firebase/auth';
import { useNavigate } from 'react-router-dom';
import Spinner from '../components/Spinner';
const CreateListing = () => {
const [geoLocationEnabled, setGeolocationEnabled] = useState(true);
const [loading, setLoading] = useState(false);
const [formData, setFormData] = useState({
type: 'rent',
name: '',
bedrooms: 1,
bathrooms: 1,
parking: false,
furnished: false,
address: '',
offer: false,
regularPrice: 0,
discountedPrice: 0,
images: {},
latitude: 0,
longitude: 0
});
const auth = getAuth();
const navigate = useNavigate();
const isMounted = useRef(true);
useEffect(() => {
if (isMounted.current) {
onAuthStateChanged(auth, (user) => {
if (user) {
setFormData({
...formData,
userRef: user.uid
});
}
else {
navigate('/sign-in');
}
});
}
return () => {
isMounted.current = false;
}
}, []);
if (loading) {
return <Spinner />
}
return (
<div>CreateListing</div>
)
}
export default CreateListing
我收到这个错误:
React Hook useEffect has missing dependencies: 'auth', 'formData', and 'navigate'. Either include them or remove the dependency array. You can also do a functional update 'setFormData(f => ...)' if you only need 'formData' in the 'setFormData' call react-hooks/exhaustive-deps
为了解决它,我在 useEffect 数组中添加了 isMounted 作为依赖项,并在依赖项数组行上方添加了 // eslint-disable-next-line
行。这确实解决了警告并且一切正常。但是,这段代码仍然存在问题。尽管,当组件卸载时,onAuthStatus 侦听器实际上仍然 运行,但它无法执行任何操作。
我找到了一个更好的解决方案,其中指出 onAuthStatus() return 是一种取消订阅方法,可以在 useEffect 的 return 函数中调用。这将确保侦听器确实取消订阅并在组件卸载时确实导致任何内存泄漏。
onAuthStatus 文档的 link 是:
https://firebase.google.com/docs/reference/js/auth.auth.md#authonauthstatechanged
此外,请注意,当我点击 Returns: 下的取消订阅 link 时,出现 404 错误...这很不正常
我认为下面的解决方案应该更好,但我不确定:
useEffect(()=>{
const unsub = onAuthStateChanged(auth, (user)=>{
if (user) {
setFormData({
...formData,
userRef: user.uid
});
}
else {
navigate('/sign-in');
}
});
return unsub();
},[]);
有人可以指导我这种方法吗?如果有更好的解决方案,请分享...在此先感谢您。
你在做什么应该没问题。虽然在全局级别为整个应用程序设置单个侦听器是完全可以的(没有钩子)。那个听众并没有真正“泄漏”任何东西。只要用户的状态发生变化,它就会不断被调用,因此您可以决定在发生这种情况时要为整个应用程序做什么。
这是我的代码:
import React, {useState, useRef, useEffect} from 'react';
import { getAuth, onAuthStateChanged } from 'firebase/auth';
import { useNavigate } from 'react-router-dom';
import Spinner from '../components/Spinner';
const CreateListing = () => {
const [geoLocationEnabled, setGeolocationEnabled] = useState(true);
const [loading, setLoading] = useState(false);
const [formData, setFormData] = useState({
type: 'rent',
name: '',
bedrooms: 1,
bathrooms: 1,
parking: false,
furnished: false,
address: '',
offer: false,
regularPrice: 0,
discountedPrice: 0,
images: {},
latitude: 0,
longitude: 0
});
const auth = getAuth();
const navigate = useNavigate();
const isMounted = useRef(true);
useEffect(() => {
if (isMounted.current) {
onAuthStateChanged(auth, (user) => {
if (user) {
setFormData({
...formData,
userRef: user.uid
});
}
else {
navigate('/sign-in');
}
});
}
return () => {
isMounted.current = false;
}
}, []);
if (loading) {
return <Spinner />
}
return (
<div>CreateListing</div>
)
}
export default CreateListing
我收到这个错误:
React Hook useEffect has missing dependencies: 'auth', 'formData', and 'navigate'. Either include them or remove the dependency array. You can also do a functional update 'setFormData(f => ...)' if you only need 'formData' in the 'setFormData' call react-hooks/exhaustive-deps
为了解决它,我在 useEffect 数组中添加了 isMounted 作为依赖项,并在依赖项数组行上方添加了 // eslint-disable-next-line
行。这确实解决了警告并且一切正常。但是,这段代码仍然存在问题。尽管,当组件卸载时,onAuthStatus 侦听器实际上仍然 运行,但它无法执行任何操作。
我找到了一个更好的解决方案,其中指出 onAuthStatus() return 是一种取消订阅方法,可以在 useEffect 的 return 函数中调用。这将确保侦听器确实取消订阅并在组件卸载时确实导致任何内存泄漏。
onAuthStatus 文档的 link 是:
https://firebase.google.com/docs/reference/js/auth.auth.md#authonauthstatechanged
此外,请注意,当我点击 Returns: 下的取消订阅 link 时,出现 404 错误...这很不正常
我认为下面的解决方案应该更好,但我不确定:
useEffect(()=>{
const unsub = onAuthStateChanged(auth, (user)=>{
if (user) {
setFormData({
...formData,
userRef: user.uid
});
}
else {
navigate('/sign-in');
}
});
return unsub();
},[]);
有人可以指导我这种方法吗?如果有更好的解决方案,请分享...在此先感谢您。
你在做什么应该没问题。虽然在全局级别为整个应用程序设置单个侦听器是完全可以的(没有钩子)。那个听众并没有真正“泄漏”任何东西。只要用户的状态发生变化,它就会不断被调用,因此您可以决定在发生这种情况时要为整个应用程序做什么。