Reactjs 防止“useEffect”循环
我有一个简单的Useffect,我不知道如何停止无休止的调用。它不断地发射第一个信号,如果有条件的话。我已经读了很多关于钩子的书,我可能错误地认为组件的每个呈现都会导致对我的useAuth和useUser钩子的新调用。因为它们在内存中有新的引用,它触发了useEffect的deps,因为从技术上讲,它是一个新函数,存在于这个新组件render的范围内 至少这是我的想法,如果真的是那样的话,我不知道如何解决这个问题Reactjs 防止“useEffect”循环,reactjs,firebase-authentication,react-hooks,use-effect,Reactjs,Firebase Authentication,React Hooks,Use Effect,我有一个简单的Useffect,我不知道如何停止无休止的调用。它不断地发射第一个信号,如果有条件的话。我已经读了很多关于钩子的书,我可能错误地认为组件的每个呈现都会导致对我的useAuth和useUser钩子的新调用。因为它们在内存中有新的引用,它触发了useEffect的deps,因为从技术上讲,它是一个新函数,存在于这个新组件render的范围内 至少这是我的想法,如果真的是那样的话,我不知道如何解决这个问题 const RootPage = ({ Component, pageProps
const RootPage = ({ Component, pageProps }): JSX.Element => {
const { logoutUser } = useAuth(); // imported
const { fetchUser } = useUser(); // imported
const router = useRouter();
useEffect(() => {
// authStatus();
const unsubscribe = firebaseAuth.onAuthStateChanged((user) => {
if (user) {
console.log(1);
return fetchUser(user.uid); // async function that fetches from db and updates redux
}
console.log(2);
return logoutUser(); // clears userData in redux
});
return () => unsubscribe();
}, [fetchUser, logoutUser]);
...
}
获取用户
注销用户
当我使用此useEffect刷新页面时,会将其输出到控制台:
使用useCallback将fetchUser和resetUser保持不变&&wrapping,此解决方案似乎工作正常。我现在还不完全清楚为什么。在自定义挂钩中,需要在useCallback中包装logoutUser和fetchUser函数。请查看useCallback文档以获取解释。如果该效果持续触发,可能是因为其依赖项正在更改,也可能是因为您正在安装新组件。。。很难说没有看到更多的代码。实际上,我想可能是我用UseCallback包装了一个错误的函数,whoopsUsecallback阻止函数被重新定义,除非依赖项数组中的一个依赖项发生变化。因此,不会在每次渲染时重新定义包装函数,从而防止在每次渲染时触发useEffect。你基本上是在记忆函数。这是有道理的,我认为useCallback必须在组件主体内调用,但显然它也可以在自定义钩子内调用。没错,虽然从技术上讲它只能在组件主体内调用,因为钩子只在组件主体内调用。是一样的。
const fetchUser = async (uid) => {
try {
// find user doc with matching id
const response = await firebaseFirestore
.collection('users')
.doc(uid)
.get();
const user = response.data();
// update redux with user
if (response) {
return dispatch({
type: FETCH_USER,
payload: user,
});
}
console.log('no user found');
} catch (error) {
console.error(error);
}
};
const logoutUser = async () => {
try {
// logout from firebase
await firebaseAuth.signOut();
// reset user state in redux
resetUser();
return;
} catch (error) {
console.error(error);
}
};
useEffect(() => {
function onAuthStateChange() {
return firebaseAuth.onAuthStateChanged((user) => {
if (user) {
fetchUser(user.uid);
} else {
resetUser();
}
});
}
const unsubscribe = onAuthStateChange();
return () => {
unsubscribe();
};
}, [fetchUser, resetUser]);