# #firebase #react-native #expo
Вопрос:
Я новичок в Экспо и реагирую. На данный момент я разрабатываю мобильное приложение, которое использует авторизацию Firebase и Firestore для аутентификации и профиля пользователя. Погуглив, я нашел решение использовать ContextProvider для аутентификации Firebase. Я попытался настроить код, чтобы одновременно получить профиль.
Это код для AuthenticatedUserProvider.js
import React, { useState, createContext } from 'react';
export const AuthenticatedUserContext = createContext({});
export const AuthenticatedUserProvider = ({ children }) => {
const [user, setUser] = useState(null);
const [profile, setProfile] = useState(null);
return (
<AuthenticatedUserContext.Provider value={{ user, setUser, profile, setProfile }}>
{children}
</AuthenticatedUserContext.Provider>
);
};
И я прочитал profile
об RotNavigator.js
этом ниже
import React, { useContext, useEffect, useState } from 'react';
import { View, ActivityIndicator } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import * as eva from '@eva-design/eva';
import { ApplicationProvider, IconRegistry } from '@ui-kitten/components';
import { EvaIconsPack } from '@ui-kitten/eva-icons';
import { auth, fs } from '../config/firebase';
import { AuthenticatedUserContext } from './AuthenticatedUserProvider';
import AuthStack from './AuthStack';
import HomeStack from './HomeStack';
import { default as theme } from '../orange-theme.json';
export default function RootNavigator() {
const { user, setUser, profile, setProfile } = useContext(AuthenticatedUserContext);
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
// onAuthStateChanged returns an unsubscribe
const unsubscribeAuth = auth.onAuthStateChanged(async authenticatedUser => {
try {
if (authenticatedUser) {
await setUser(authenticatedUser)
const response = await fs.collection("members").doc(authenticatedUser.uid).get();
if (response.exists) {
let data = response.data();
// console.log(data);
await setProfile(data);
// console.log(profile);
}
} else {
await setUser(null);
await setProfile(null);
}
setIsLoading(false);
} catch (error) {
console.log(error);
}
});
// unsubscribe auth listener on unmount
return unsubscribeAuth;
}, []);
if (isLoading) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<ActivityIndicator size='large' />
</View>
);
}
return (
<>
<IconRegistry icons={EvaIconsPack} />
<ApplicationProvider {...eva} theme={{ ...eva.light, ...theme }}>
<NavigationContainer>
{user ? <HomeStack /> : <AuthStack />}
</NavigationContainer>
</ApplicationProvider >
</>
);
}
Код выглядит как рабочий, за исключением того, что, если я войду в систему, иногда я вижу ошибку в профиле = null и не могу прочитать профиль, но затем он обновляется сам по себе и возвращается для правильной работы.
Может ли кто-нибудь подсказать правильный способ отображения профиля из Firestore?
Причина, по которой я делаю это так, заключается в том, что мне нужен эффективный способ отображения профиля, поскольку в HomeStack есть 3 экрана, на которых должны отображаться некоторые части профиля на каждом экране.
Спасибо вам за вашу помощь.
Комментарии:
1. Вам действительно нужен отдельный пользователь аутентификации и профиль? Это происходит потому, что у вас есть два вызова setState, и они не гарантированно срабатывают вместе, поэтому у вас будут некоторые крайние случаи, когда срабатывает один, но не другой, и вы увидите проблемы, подобные тем, которые вы видите. Что вам нужно от записи пользователя auth? Только жидкость? Почему бы не добавить это в профиль и ТОЛЬКО
setProfile
. Затем, когда пользователь выходит из системы, та же идея — простоsetProfile(null)
.2. Спасибо вам за ваши отзывы. Мне не нужен отдельный пользователь. Это правда, что мне нужно только
uid
то . Я постараюсь это реализовать.3. @I’Mjoetoo, но я вызываю setUser с помощью wait, разве это не означает, что нужно дождаться завершения setUser, прежде чем вызывать setProfile? и визуализировать после завершения загрузки setProfile?
4. Для обещаний
await
означает, что строка будет выполнена и завершена, прежде чем перейти к следующей. Но в ReactuseState
это не основано на обещаниях. Когда выsetUser
и устанавливаете другие состояния, они добавляются в очередь, а затем выполняются позже — в течение микросекунд, но без гарантированного порядка, поэтому вы периодически получаете эти странные состояния. ПотомуuseState
что тыawait
здесь ничего не делаешь.5. привет @I’Mjoetoo спасибо за отличное объяснение. Я думаю, что исправил свою проблему, изменив эту строку {профиль ? <HomeStack /> : <HomeStack /><AuthStack />} . поэтому вместо того, чтобы полагаться на пользователя, которого нужно настроить, я полагался на профиль. если они вошли в систему, но профиль еще не установлен, им будет предложено снова войти в систему. но пока с помощью этого исправления я могу избавиться от сообщения об ошибке