使用上下文和Firebase,我尝试使用onAuthStateChange在应用程序中设置我的用户。收到用户的useEffect后,将再次运行并返回null。
import React, { createContext, useState, useEffect } from 'react';
import { withFirebase } from '../Firebase';
// the context
const AuthUserContext = createContext();
// the higher order (wrapper)
const PureAuthState = ({ children, firebase }) => {
const [authState, setAuthState] = useState({
authUser: null,
});
const { auth } = firebase;
const onChange = authUser => {
console.log(authUser);
setAuthState({ authUser });
};
useEffect(() => {
const unsubscribe = auth.onAuthStateChanged(onChange);
// avoid memory leaks??
return () => {
unsubscribe();
};
// eslint-disable-next-line
}, []);
return (
<AuthUserContext.Provider value={{ authState, setAuthState }}>
{children}
</AuthUserContext.Provider>
);
};
export const AuthState = withFirebase(PureAuthState);
export default AuthUserContext;
这些是我从浏览器的console.log中获得的内容
//// the user
context.js:12 P {G: Array(0), l: "AIzaSyBOAb8pWO...}
//// null
context.js:12 null
我不明白为什么之后会得到这个空值。正常运行2天后,发生了这种情况。救命!
编辑1: 这是我的登录组件。我认为这是这个问题的根源。
const SignInFormBase = props => {
const [form, setVal] = useState({
email: '',
password: '',
error: null,
});
const { firebase, history } = props;
const { email, password, error } = form;
const signIn = async () => {
await firebase.doSignInWithEmailAndPassword(email, password);
setVal({ ...form });
history.push(ROUTES.HOME);
};
const onSubmit = e => {
try {
signIn();
// history.push(ROUTES.HOME);
} catch (err) {
setVal({ ...form, error: err });
}
e.preventDefault();
};
如果我将history.push到signIn函数之外,则会收到此警告,并且之后仍然仍然将authUser设置为null。
Warning: 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.
答案 0 :(得分:0)
我不太确定您的代码设置如何,但是如果您要获取经过身份验证的用户,则可以在构造函数中执行此操作,然后调度适当的操作。
例如(ngrx 7语法):
constructor(
...
) {
firebase.auth().onAuthStateChanged(user => {
// No authenticated user, logout
if (!user) {
return this.store.dispatch(new ActionAuthLogout());
}
// User is authenticated, load user document
else if (user) {
return this.store.dispatch(new ActionLoadUser());
}
});
}
答案 1 :(得分:0)
通过{ authState, setAuthState }
时,您将在每次渲染时传递一个新引用
const PureAuthState = ({ children, firebase }) => {
//.. rest removed for brevity.
return (
<AuthUserContext.Provider value={{ authState, setAuthState }}>
{children}
</AuthUserContext.Provider>
);
};
在将值传递给上下文之前,您会记住它吗?
const PureAuthState = ({ children, firebase }) => {
//.. rest removed for brevity.
const contextValue = React.memo(() => ({ authState, setAuthState }), [
authState,
setAuthState
]);
return (
<AuthUserContext.Provider value={contextValue}>
{children}
</AuthUserContext.Provider>
);
};