Я делаю мобильное приложение, используя React Native (0.61.2) и TypeScript (3.6.4). Я использую Firebase Authentication и Firebase Firestore из React Native Firebase collection.
Я пытаюсь:
- Прослушивание изменений состояния аутентификации (с помощью onAuthStateChanged)
- Прослушивание изменений аутентификации пользователя (с использованием onUserChanged)
- Прослушивание документа пользователя (с использованием onSnapshot)
- Прослушивание определенного документа под названием brand (с использованием onSnapshot)
Я сохраняю в контексте userAuth, документ пользователя и документ бренда от предыдущих слушателей.
/**
* Types
*/
type UserAuth = FirebaseAuthTypes.User | null;
type User = UserDoc | null;
type Brand = BrandDoc | null;
type ContextProps = {
userAuth: UserAuth;
user: User;
brand: Brand;
} | null;
/**
* Context
*/
export const Context = createContext<ContextProps>(null);
function App() {
const [initializing, setInitializing] = useState(true);
const [listenUserAuth, setListenUserAuth] = useState(false);
const [userAuth, setUserAuth] = useState<UserAuth>(null);
const [listenUser, setListenUser] = useState(false);
const [user, setUser] = useState<User>(null);
const [listenBrand, setListenBrand] = useState(false);
const [brand, setBrand] = useState<Brand>(null);
/** Listen for auth state changes */
useEffect(() => {
const authListener = auth().onAuthStateChanged(result => {
setUserAuth(result);
if (initializing && !listenUserAuth) {
setInitializing(false);
setListenUserAuth(true);
setListenUser(true);
setListenBrand(true);
}
});
return () => {
if (authListener) {
console.log('removing auth state listener');
authListener();
}
};
}, [initializing, listenUserAuth]);
/** Listen for user auth changes */
useEffect(() => {
let userAuthListener: () => void;
if (listenUserAuth) {
userAuthListener = auth().onUserChanged(result => {
setUserAuth(result);
});
}
return () => {
if (userAuthListener) {
console.log('removing user auth listener');
userAuthListener();
}
};
}, [listenUserAuth]);
/** Listen for user document changes */
useEffect(() => {
let userListener: () => void;
if (listenUser) {
if (!userAuth) {
return;
}
console.log('listening user document');
userListener = firestore()
.collection('users')
.doc(userAuth.uid)
.onSnapshot(querySnapshot => {
console.log('User querySnapshot: ', querySnapshot.data());
setUser(querySnapshot.data());
});
}
return () => {
if (userListener) {
console.log('removing user document listener');
userListener();
}
};
}, [listenUser, userAuth]);
/** Listen for brand document changes */
useEffect(() => {
let brandListener: () => void;
if (listenBrand) {
if (!userAuth) {
return;
}
console.log('listening brand document');
brandListener = firestore()
.collection('brands')
.doc('31uOUtUkVYg8z953UdxS')
.onSnapshot(querySnapshot => {
console.log('Brand querySnapshot: ', querySnapshot.data());
setBrand(querySnapshot.data());
});
}
return () => {
if (brandListener) {
console.log('removing brand document listener');
brandListener();
}
};
}, [listenBrand, userAuth]);
if (initializing) {
return (
<View style={{flex: 1, justifyContent: 'center'}}>
<ActivityIndicator size="large" color="#000" />
</View>
);
}
function container(children: ReactNode | ReactNode[]) {
return <PaperProvider theme={theme}>{children}</PaperProvider>;
}
return container(
userAuth && user && brand ? (
<Context.Provider value={{userAuth, user, brand}}>
<SignedInStack />
</Context.Provider>
) : (
<SignedOutStack />
)
);
}
export default App;
В другом компоненте, когда пользователь выходит из системы, все слушатели снова слушают и удаляютсам по себе несколько раз.
Журналы:
Это добавляет ненужные операции чтения и записи в Firebase, которыеувеличить расходы.
Я новичок в использовании useEffect , и я почти уверен, что делаю что-то не так. Я не совсем понимаю зависимости, необходимые для использования useEffect для начала прослушивания документа пользователя и документа бренда и удаления слушателей один раз. Я попытался прочитать, прежде чем сделать это, и я подумал, что все правильно.
- Кроме того, по какой-то причине, которую я не вижу, ActivityIndicator удаляется без документа пользователяи документ бренда. Он должен отображаться до тех пор, пока не будут заданы параметры UserAuth, User и Brand.
Моя цель здесь:
- Показывать ActivityIndicator до тех пор, пока не будут установлены все прослушиватели.
- Прослушивайте и удаляйте слушателей только один раз, чтобы избежать ненужных операций чтения и записи.