Firebase kimlik doğrulama modeli tarafından oluşturulan özniteliklerle birleştirilen bir kullanıcı koleksiyonunda depolanan bir öznitelik olan bir kullanıcı adı almak nasıl anlamaya çalışıyorum.
Bana kimlik doğrulama aracında firebase topladığı sınırlı alanları veren authUser erişebilir ve sonra (aynı uid kullanan) ilgili kullanıcı koleksiyonuna oradan almaya çalışıyorum.
Ben bir tepki bağlam tüketici ile var:
import React from 'react';
const AuthUserContext = React.createContext(null);
export default AuthUserContext;
Sonra benim bileşeninde kullanmaya çalışıyorum:
const Test = () => (
<AuthUserContext.Consumer>
{authUser => (
<div>
{authUser.email} // I can access the attributes in the authentication collection
{authUser.uid.user.name} //i cannot find a way to get the details in the related user collection document - where the uid on the collection is the same as the uid on the authentication table
</div>
)}
</AuthUserContext.Consumer>
);
const condition = authUser => !!authUser;
export default compose(
withEmailVerification,
withAuthorization(condition),
)(Test);
Benim firebase.js - Bence Kimlik Doğrulama modelinden authUser özniteliklerini kullanıcı toplama öznitelikleri ile aşağıdaki gibi birleştirmeye çalıştım:
class Firebase {
constructor() {
app.initializeApp(config).firestore();
/* helpers */
this.fieldValue = app.firestore.FieldValue;
/* Firebase APIs */
this.auth = app.auth();
this.db = app.firestore();
onAuthUserListener = (next, fallback) =>
this.auth.onAuthStateChanged(authUser => {
if (authUser) {
this.user(authUser.uid)
.get()
.then(snapshot => {
const dbUser = snapshot.data();
// default empty roles
if (!dbUser.roles) {
dbUser.roles = {};
}
// merge auth and db user
authUser = {
uid: authUser.uid,
email: authUser.email,
emailVerified: authUser.emailVerified,
providerData: authUser.providerData,
...dbUser,
};
next(authUser);
});
} else {
fallback();
}
});
Kimlik Doğrulama koleksiyonundan aynı kullanıcı kimliğine sahip bir kimliğe sahip kullanıcı koleksiyonuna authUser'den (Kimlik Doğrulama özniteliklerine ulaşmak için çalışır) bir yol bulamıyorum.
Aynı soruna sahip gibi görünen ve cevabın ima ettiği şeyleri bulmaya çalıştığım bu yayını gördüm - ancak Kimlik Doğrulama koleksiyonundan kullanıcı koleksiyonuna ulaşmak için çalışan bir yol bulamıyorum authUser kullanıcı koleksiyonundaki özelliklere erişmeme izin vermiyorsa birleştirme işleminin benim için ne yaptığını bilmiyorum.
Bir kullanıcı bana bir kullanıcı vermek için firebase.js bir yardımcı kullanmaya çalıştı - ama bu da yardımcı gibi görünmüyor.
user = uid => this.db.doc(`users/${uid}`);
users = () => this.db.collection('users');
Bir sonraki deneme
Daha fazla arka plan eklemek için aşağıdaki gibi authUser günlüğü (ama render değil) bir test bileşeni yaptık:
import React, { Component } from 'react';
import { withFirebase } from '../Firebase/Index';
import { Button, Layout } from 'antd';
import { AuthUserContext, withAuthorization, withEmailVerification } from '../Session/Index';
class Test extends Component {
constructor(props) {
super(props);
this.state = {
loading: false,
user: null,
...props.location.state,
};
}
componentDidMount() {
if (this.state.user) {
return;
}
this.setState({ loading: true });
// this.unsubscribe = this.props.firebase
// .user(authUser.uid)
// .onSnapshot(snapshot => {
// const userData = snapshot.data();
// console.log(userData);
// this.setState({
// user: snapshot.data(),
// loading: false,
// });
// });
}
componentWillUnmount() {
this.unsubscribe && this.unsubscribe();
}
render() {
const { user, loading } = this.state;
return (
<div>
<AuthUserContext.Consumer>
{authUser => (
console.log(authUser),
<p>
</p>
)}
</AuthUserContext.Consumer>
</div>
);
};
}
export default Test;
Günlük, günlüklerde uid, e-posta vb. İçin ayrıntıları gösterir, ancak çoğu 1 veya 2 harfle ön sırada olan uzun bir öğe listesinin arasındadır (bu öneklerin her birini bulmak için bir anahtar bulamıyorum harfler anlamına gelir). Aşağıda çıkarılan örnek:
BU YORUMDA GÜNCELLEME:
Önceden, dedim: uid, e-posta vb alanları bu öneklerin altında yuvalanmış gibi görünmüyor, ancak şunu denerseniz:
console.log(authUser.email)
, Bir hata mesajı alıyorum:
TypeError: null özelliği 'e-posta' okunamıyor
Güncelleme: Konsol günlüğünde etiketli bir açılır menüyü genişletmem gerektiğini fark ettim:
Q {I: Dizi (0), l:
e-posta özelliğini görmek için. Herkes bu nimetin ne anlama geldiğini biliyor mu? Kimlik Doğrulama tablosundaki ilgili özniteliklere ulaşmak için bunlara atıfta bulunup bulunmamam gerektiğini bilmek için Q, I veya l'in ne anlama geldiğini anlamak için bir anahtar bulamıyorum. Belki anlayabiliyorsam - Kimlik Doğrulama koleksiyonundan uid kullanarak kullanıcı koleksiyonuna ulaşmak için bir yol bulabilirim.
Mevcut kullanıcının kim olduğunu bulmak için bağlam tüketicisi ile kullanıcı ön tarafta tepki gösterdi mi? Öyleyse, Kimlik Doğrulama modelindeki özniteliklerine nasıl erişiyorsunuz ve ilgili Kullanıcı koleksiyonundaki özniteliklere nasıl eriştiniz (Kullanıcı belgesindeki docId, Kimlik Doğrulama tablosundan uid'dir)?
SONRAKİ GİRİŞ
Bir sonraki girişim çok garip bir sonuç doğurdu.
Bağlam tüketicisi olan 2 ayrı sayfam var. Aralarındaki fark, birinin bir işlev ve diğerinin bir sınıf bileşenidir.
Fonksiyon bileşeninde {authUser.email} oluşturabilirim. Sınıf bileşeninde aynı şeyi yapmaya çalıştığımda, şöyle bir hata alıyorum:
TypeError: null özelliği 'e-posta' okunamıyor
Bu hata, oturum açmış aynı kullanıcıyla aynı oturumdan geliyor.
Not: Firebase belgeleri, bir currentUser özelliğinin auth üzerinde kullanılabilir olduğunu söylese de - bunu hiç çalıştıramadım.
İşlev bileşenim şunları içerir:
import React from 'react';
import { Link } from 'react-router-dom';
import { compose } from 'recompose';
import { AuthUserContext, withAuthorization, withEmailVerification } from '../Session/Index';
const Account = () => (
<AuthUserContext.Consumer>
{authUser => (
<div>
{authUser.email}
</div>
)}
</AuthUserContext.Consumer>
);
// const condition = authUser => !!authUser;
// export default compose(
// withEmailVerification,
// withAuthorization(condition),
// )(Account);
export default Account;
Kullanıcı belgesindeki docId'nin kimliği doğrulanmış kullanıcının uidiyle aynı olduğu Kullanıcı koleksiyonu özniteliklerine erişemesem de, bu bileşenden bu kullanıcının kimlik doğrulama koleksiyonundaki e-posta özniteliğini çıktılayabilirim.
Firebase belgeleri , kullanıcıları yönetmek ve buradaki özelliklere erişmek için bu tavsiyeyi sunarken, bu yaklaşımı tepki olarak uygulamak için bir yol bulamadım. Bunu yapmak için yapılan bir girişimin her varyasyonu, hem firebase.js dosyamda yardımcılar oluşturarak hem de bir bileşende sıfırdan başlamaya çalışarak ateş tabanına erişimde hatalar üretir. Ancak kullanıcıların bir listesini ve ilgili Kullanıcı toplama bilgilerini üretebilirim (authUser'ın kim olduğuna bağlı olarak bir kullanıcı alamıyorum).
Sınıf bileşenim:
import React from 'react';
import {
BrowserRouter as Router,
Route,
Link,
Switch,
} from 'react-router-dom';
import * as ROUTES from '../../constants/Routes';
import { compose } from 'recompose';
import { withFirebase } from '../Firebase/Index';
import { AuthUserContext, withAuthorization, withEmailVerification } from '../Session/Index';
class Dashboard extends React.Component {
state = {
collapsed: false,
};
onCollapse = collapsed => {
console.log(collapsed);
this.setState({ collapsed });
};
render() {
const { loading } = this.state;
// const dbUser = this.props.firebase.app.snapshot.data();
// const user = Firebase.auth().currentUser;
return (
<AuthUserContext.Consumer>
{authUser => (
<div>
{authUser.email} // error message as shown above
{console.log(authUser)} // output logged in amongst a long list of menus prefixed with either 1 or 2 characters. I can't find a key to decipher what these menus mean or do.
</div>
)}
</AuthUserContext.Consumer>
);
}
}
//export default withFirebase(Dashboard);
export default Dashboard;
Benim AuthContext.Provider - var:
import React from 'react';
import { AuthUserContext } from '../Session/Index';
import { withFirebase } from '../Firebase/Index';
const withAuthentication = Component => {
class WithAuthentication extends React.Component {
constructor(props) {
super(props);
this.state = {
authUser: null,
};
}
componentDidMount() {
this.listener = this.props.firebase.auth.onAuthStateChanged(
authUser => {
authUser
? this.setState({ authUser })
: this.setState({ authUser: null });
},
);
}
componentWillUnmount() {
this.listener();
};
render() {
return (
<AuthUserContext.Provider value={this.state.authUser}>
<Component {...this.props} />
</AuthUserContext.Provider>
);
}
}
return withFirebase(WithAuthentication);
};
export default withAuthentication;
SONRAKİ GİRİŞ
Gerçekten bu girişim ile, ben veritabanında var gördüğünüz değerleri günlüğü konsol çalışıyorum ve ad değeri db içinde bir dize vardır 'undefined' olarak döndürülüyor garip.
Bu girişimde şunlar var:
import React from 'react';
import {
BrowserRouter as Router,
Route,
Link,
Switch,
useRouteMatch,
} from 'react-router-dom';
import * as ROUTES from '../../constants/Routes';
import { compose } from 'recompose';
import { withFirebase } from '../Firebase/Index';
import { AuthUserContext, withAuthorization, withEmailVerification } from '../Session/Index';
class Dash extends React.Component {
// state = {
// collapsed: false,
// };
constructor(props) {
super(props);
this.state = {
collapsed: false,
loading: false,
user: null,
...props.location.state,
};
}
componentDidMount() {
if (this.state.user) {
return;
}
this.setState({ loading: true });
this.unsubscribe = this.props.firebase
.user(this.props.match.params.id)
// .user(this.props.user.uid)
// .user(authUser.uid)
// .user(authUser.id)
// .user(Firebase.auth().currentUser.id)
// .user(Firebase.auth().currentUser.uid)
.onSnapshot(snapshot => {
this.setState({
user: snapshot.data(),
loading: false,
});
});
}
componentWillUnmount() {
this.unsubscribe && this.unsubscribe();
}
onCollapse = collapsed => {
console.log(collapsed);
this.setState({ collapsed });
};
render() {
// const { loading } = this.state;
const { user, loading } = this.state;
// let match = useRouteMatch();
// const dbUser = this.props.firebase.app.snapshot.data();
// const user = Firebase.auth().currentUser;
return (
<AuthUserContext.Consumer>
{authUser => (
<div>
{loading && <div>Loading ...</div>}
<Layout style={{ minHeight: '100vh' }}>
<Sider collapsible collapsed={this.state.collapsed} onCollapse={this.onCollapse}>
<div />
</Sider>
<Layout>
<Header>
{console.log("authUser:", authUser)}
// this log returns the big long list of outputs - the screen shot posted above is an extract. It includes the correct Authentication table (collection) attributes
{console.log("authUser uid:", authUser.uid)}
// this log returns the correct uid of the current logged in user
{console.log("Current User:", this.props.firebase.auth.currentUser.uid)}
// this log returns the correct uid of the current logged in user
{console.log("current user:", this.props.firebase.db.collection("users").doc(this.props.firebase.auth.currentUser.uid
))}
// this log returns a big long list of things under a heading: DocumentReference {_key: DocumentKey, firestore: Firestore, _firestoreClient: FirestoreClient}. One of the attributes is: id: (...) (I can't click to expand this).
{console.log("current user:", this.props.firebase.db.collection("users").doc(this.props.firebase.auth.currentUser.uid
).name)}
//this log returns: undefined. There is an attribute in my user document called 'name'. It has a string value on the document with the id which is the same as the currentUser.uid.
<Text style={{ float: 'right', color: "#fff"}}>
{user && (
<Text style={{ color: "#fff"}}>{user.name}
//this just gets skipped over in the output. No error but also does not return the name.
</Text>
)}
</Text>
</Header>
</Layout>
</Layout>
</div>
)}
</AuthUserContext.Consumer>
);
}
}
export default withFirebase(Dash);
SONRAKİ GİRİŞ
Bu nedenle bu girişim beceriksizdir ve yukarıda kullanmaya çalıştığım yardımcıları veya anlık görüntü sorgularını kullanmaz, ancak kullanıcı toplama belgesi niteliklerini konsola aşağıdaki gibi günlüğe kaydedin:
{this.props.firebase.db.collection ('users'). doc (authUser.uid) .get ()
.then(doc => {
console.log(doc.data().name)
})
}
Ne yapamam jsx bu adı oluşturmak için bir yol bulmak
Çıktıyı gerçekten nasıl yazdırıyorsunuz?
Denediğimde:
{
this.props.firebase.db.collection('users').doc(authUser.uid).get().data().name
}
Bir hata mesajı alıyorum:
TypeError: this.props.firebase.db.collection (...). Doc (...). Get (...). Veri bir işlev değildir
Denediğimde:
{
this.props.firebase.db.collection('users').doc(authUser.uid).get()
.then(doc => {
console.log(doc.data().name),
<p>doc.data().name</p>
})
}
Bir hata mesajı alıyorum:
Satır 281: 23: Bir atama veya işlev çağrısı bekleniyordu ve bunun yerine kullanılmayan ifadeler olmayan bir ifade gördü
Denediğimde:
{
this.props.firebase.db.collection('users').doc(authUser.uid).get("name")
.then(doc => {
console.log(doc.data().name),
<p>doc.data().name</p>
})
}
Hata mesajı şunu söylüyor:
Bir ödev veya işlev çağrısı bekleniyordu ve bunun yerine bir ifade gördü
Anlık görüntü sorgularının nasıl çalışacağını öğrenmeye çalışmaktan vazgeçmeye hazırım - eğer ekranda işlemek için kullanıcı koleksiyonunun adını alabilirsem. Herkes bu adımda yardımcı olabilir mi?
SONRAKİ GİRİŞ
Bu gönderiyi buldum . Ne olması gerektiği konusunda iyi bir açıklaması var, ancak componentDidMount authUser ne olduğunu bilmiyor çünkü gösterildiği gibi uygulayamıyorum.
Şu anki denemem şu şekildedir - ancak, şu anda yazıldığı gibi, authUser dönüş değerinde bir paketleyicidir - ve componentDidMount segmenti authUser'ın ne olduğunu bilmiyor.
import React from 'react';
import {
BrowserRouter as Router,
Route,
Link,
Switch,
useRouteMatch,
} from 'react-router-dom';
import * as ROUTES from '../../constants/Routes';
import { compose } from 'recompose';
import { Divider, Layout, Card, Tabs, Typography, Menu, Breadcrumb, Icon } from 'antd';
import { withFirebase } from '../Firebase/Index';
import { AuthUserContext, withAuthorization, withEmailVerification } from '../Session/Index';
const { Title, Text } = Typography
const { TabPane } = Tabs;
const { Header, Content, Footer, Sider } = Layout;
const { SubMenu } = Menu;
class Dashboard extends React.Component {
// state = {
// collapsed: false,
// loading: false,
// };
constructor(props) {
super(props);
this.state = {
collapsed: false,
loading: false,
user: null,
...props.location.state,
};
}
componentDidMount() {
if (this.state.user) {
return;
}
this.setState({ loading: true });
this.unsubscribe = this.props.firebase
.user(this.props.match.params.id)
.onSnapshot(snapshot => {
this.setState({
user: snapshot.data(),
loading: false,
});
});
// }
// firebase.firestore().collection("users")
// .doc(this.state.uid)
// .get()
// .then(doc => {
// this.setState({ post_user_name: doc.data().name });
// });
// }
this.props.firebase.db
.collection('users')
.doc(authUser.uid)
.get()
.then(doc => {
this.setState({ user_name: doc.data().name });
// loading: false,
});
}
componentWillUnmount() {
this.unsubscribe && this.unsubscribe();
}
onCollapse = collapsed => {
console.log(collapsed);
this.setState({ collapsed });
};
render() {
// const { loading } = this.state;
// const { user, loading } = this.state;
// let match = useRouteMatch();
// const dbUser = this.props.firebase.app.snapshot.data();
// const user = Firebase.auth().currentUser;
return (
<AuthUserContext.Consumer>
{ authUser => (
<div>
<Header>
{/*
{
this.props.firebase.db.collection('users').doc(authUser.uid).get()
.then(doc => {
console.log( doc.data().name
)
})
}
*/}
</Text>
</Header>
<Switch>
</Switch>
</div>
)}
</AuthUserContext.Consumer>
);
}
}
export default withFirebase(Dashboard);
SONRAKİ GİRİŞ
Daha sonra, tüm bileşenin kullanabilmesi için AuthContext.Consumer içindeki gösterge tablosu için güzergahı kaydırmayı denedim - böylece beni componentDidMount işlevinde oturum açmış kullanıcıya erişmesine izin verin.
Rotayı şu şekilde değiştirdim:
<Route path={ROUTES.DASHBOARD} render={props => (
<AuthUserContext.Consumer>
{ authUser => (
<Dashboard authUser={authUser} {...props} />
)}
</AuthUserContext.Consumer>
)} />
ve müşteriyi gösterge tablosu bileşeni oluşturma ifadesinden kaldırdı.
Sonra Pano bileşenindeki componentDidMount, denedim:
componentDidMount() {
if (this.state.user) {
return;
}
this.setState({ loading: true });
this.unsubscribe =
this.props.firebase.db
.collection('users')
//.doc(this.props.firebase.db.collection('users').doc(this.props.firebase.authUser.uid))
.doc(this.props.firebase.db.collection('users').doc(this.props.authUser.uid))
.get()
.then(doc => {
this.setState({ name: doc.data().name });
loading: false,
});
}
Bunu denediğimde, şöyle bir hata alıyorum:
FirebaseError: Function CollectionReference.doc (), ilk bağımsız değişkeninin boş olmayan dize türünde olmasını gerektirir, ancak şuydu: özel bir DocumentReference nesnesi
SONRAKİ GİRİŞ Aşağıdaki kişiler ilk önerilen çözümde yararlı bir şeyler bulmuş gibi görünüyor. İçinde yararlı bir şey bulamadım, ancak önerilerini tekrar okudum, Firebase belgelerindeki örneğin nasıl .doc () isteğine nasıl: uid değeri verileceğini açıklamıyor ), aşağıdaki gibidir:
db.collection("cities").doc("SF");
docRef.get().then(function(doc) {
if (doc.exists) {
console.log("Document data:", doc.data());
} else {
// doc.data() will be undefined in this case
console.log("No such document!");
}
temel olarak componentDidMount işlevindeki denememden farklıdır:
this.unsubscribe =
this.props.firebase.db
.collection('users')
// .doc(this.props.firebase.db.collection('users').doc(this.props.firebase.authUser.uid))
// .doc(this.props.firebase.db.collection('users').uid: this.props.firebase.auth().currentUser.uid )
.doc(this.props.authUser.uid)
.get()
.then(doc => {
this.setState({ user.name: doc.data().name });
// loading: false,
}else {
// doc.data() will be undefined in this case
console.log("Can't find this record");
}
);
}
Belki bu adımı çözmek, bunu bir sonuca doğru ilerletmeye yardımcı olacak bir ipucudur. Herkes, giriş yapmış bir kullanıcı dinleyici uid'i kullanarak bir kullanıcı toplama kaydını nasıl alacağını göstermek için daha iyi bir yangın deposu belgesi bulabilir mi?
Bu amaçla, FriendlyEats kod laboratuarı örneğinden , koddaki id arama değerine doc.id verme girişimi olduğunu görebiliyorum. Bu kodun hangi dilde yazıldığını bilmiyorum - ama yapmaya çalıştığım şeye benziyor - bu örnekten nasıl çalışacağımı bildiğim bir şeye nasıl taşınacağımı göremiyorum.
display: function(doc) {
var data = doc.data();
data['.id'] = doc.id;
data['go_to_restaurant'] = function() {
that.router.navigate('/restaurants/' + doc.id);
};