Saya mencoba mencari cara untuk mendapatkan nama pengguna yang merupakan atribut yang disimpan dalam koleksi pengguna, yang telah digabungkan dengan atribut yang dibuat oleh model otentikasi firebase.
Saya dapat mengakses authUser - yang memberi saya bidang terbatas yang dikumpulkan firebase di alat otentikasi, dan kemudian saya mencoba untuk mendapatkan dari sana ke koleksi pengguna terkait (yang menggunakan uid yang sama).
Saya memiliki konsumen konteks reaksi dengan:
import React from 'react';
const AuthUserContext = React.createContext(null);
export default AuthUserContext;
Kemudian di komponen saya, saya mencoba untuk menggunakan:
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);
Di firebase.js saya - saya pikir saya sudah mencoba untuk menggabungkan atribut authUser dari model Otentikasi dengan atribut kumpulan pengguna sebagai berikut:
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();
}
});
Saya tidak dapat menemukan cara untuk mendapatkan dari authUser (yang berfungsi untuk membawa saya ke atribut Otentikasi) - ke koleksi pengguna yang memiliki id dengan cairan yang sama dari koleksi Otentikasi.
Saya telah melihat posting ini , yang tampaknya memiliki masalah yang sama dan mencoba mencari tahu apa jawaban yang seharusnya mengisyaratkan - tapi sepertinya saya tidak dapat menemukan cara yang berfungsi untuk mendapatkan dari koleksi Otentikasi ke koleksi pengguna dan saya tidak tahu apa yang dilakukan gabungan untuk saya jika itu tidak memberi saya akses ke atribut pada kumpulan pengguna dari authUser.
Saya mencoba menggunakan helper di firebase.js untuk memberi saya pengguna dari uid - tapi itu sepertinya juga tidak membantu.
user = uid => this.db.doc(`users/${uid}`);
users = () => this.db.collection('users');
Upaya selanjutnya
Untuk menambahkan lebih banyak latar belakang, saya telah membuat komponen uji yang dapat mencatat (tetapi tidak membuat) authUser, sebagai berikut:
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;
Log menunjukkan detail untuk uid, email, dll di log, tetapi ada di antara daftar item yang panjang - banyak di antaranya diawali dengan 1 atau 2 huruf (Saya tidak dapat menemukan kunci untuk mengetahui apa yang masing-masing awalan ini. berarti huruf). Contoh diekstrak di bawah ini:
MEMPERBARUI KOMENTAR INI:
Sebelumnya, saya berkata: Bidang untuk uid, email, dll tampaknya tidak bersarang di bawah awalan ini, tetapi jika saya mencoba untuk:
console.log(authUser.email)
, Saya mendapatkan kesalahan yang mengatakan:
TypeError: Tidak dapat membaca properti 'email' dari nol
Pembaruan: Saya baru menyadari bahwa di log konsol, saya harus membuka menu tarik-turun yang berlabel:
Q {I: Array (0), l:
untuk melihat atribut email. Adakah yang tahu apa yang disinggung oleh omong kosong ini? Saya tidak dapat menemukan kunci untuk mencari tahu apa arti Q, I atau l, untuk mengetahui apakah saya seharusnya merujuk hal-hal ini untuk mendapatkan atribut yang relevan di tabel Otentikasi. Mungkin jika saya dapat mengetahuinya - saya dapat menemukan cara untuk mendapatkan koleksi pengguna menggunakan uid dari koleksi Otentikasi.
Adakah yang pernah menggunakan reaksi di ujung depan, dengan konsumen konteks untuk mencari tahu siapa pengguna saat ini? Jika demikian, bagaimana Anda mengakses atribut mereka pada model Otentikasi dan bagaimana Anda mengakses atribut pada koleksi Pengguna terkait (di mana dokumen pada dokumen Pengguna adalah cairan dari tabel Otentikasi)?
PERIKSAAN BERIKUTNYA
Upaya selanjutnya telah menghasilkan hasil yang sangat aneh.
Saya memiliki 2 halaman terpisah yang merupakan konteks konsumen. Perbedaan di antara mereka adalah bahwa satu adalah fungsi dan yang lainnya adalah komponen kelas.
Di komponen fungsi, saya bisa me-render {authUser.email}. Ketika saya mencoba melakukan hal yang sama di komponen kelas, saya mendapatkan kesalahan yang mengatakan:
TypeError: Tidak dapat membaca properti 'email' dari nol
Kesalahan ini berasal dari sesi yang sama dengan pengguna login yang sama.
Catatan: sementara dokumentasi firebase mengatakan bahwa properti User saat ini tersedia di auth - saya belum bisa membuatnya berfungsi sama sekali.
Komponen fungsi saya memiliki:
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;
Meskipun saya tidak bisa mendapatkan atribut kumpulan pengguna di mana docId pada dokumen pengguna sama dengan uid dari pengguna yang diautentikasi, dari komponen ini, saya bisa menampilkan atribut email pada koleksi auth untuk pengguna ini.
Sedangkan dokumentasi Firebase memberikan saran ini untuk mengelola pengguna dan mengakses atribut di sini, saya belum menemukan cara untuk mengimplementasikan pendekatan ini sebagai reaksi. Setiap variasi dari upaya melakukan hal ini, baik dengan membuat helper di firebase.js saya dan dengan mencoba memulai dari awal pada suatu komponen menghasilkan kesalahan dalam mengakses firebase. Namun saya dapat menghasilkan daftar pengguna dan informasi pengumpulan Pengguna terkait (saya tidak bisa mendapatkan pengguna berdasarkan siapa pengguna authUser).
Komponen kelas saya memiliki:
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;
Dalam AuthContext.Provider saya - Saya punya:
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;
PERIKSAAN BERIKUTNYA
Sangat aneh bahwa dengan upaya ini, saya mencoba untuk menghibur log nilai-nilai yang dapat saya lihat ada di database dan nilai nama dikembalikan sebagai 'tidak terdefinisi' di mana db memiliki string di dalamnya.
Upaya ini memiliki:
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);
PERIKSAAN BERIKUTNYA
Jadi upaya ini kikuk dan tidak menggunakan bantuan atau kueri snapshot yang saya coba gunakan di atas, tetapi catat atribut kumpulan dokumen pengguna ke konsol sebagai berikut:
{this.props.firebase.db.collection ('users'). doc (authUser.uid) .get ()
.then(doc => {
console.log(doc.data().name)
})
}
Yang tidak bisa saya lakukan adalah menemukan cara untuk merender nama itu di jsx
Bagaimana Anda benar-benar mencetak hasilnya?
Ketika saya mencoba:
{
this.props.firebase.db.collection('users').doc(authUser.uid).get().data().name
}
Saya mendapatkan kesalahan yang mengatakan:
TypeError: this.props.firebase.db.collection (...). Doc (...). Get (...). Data bukan fungsi
Ketika saya mencoba:
{
this.props.firebase.db.collection('users').doc(authUser.uid).get()
.then(doc => {
console.log(doc.data().name),
<p>doc.data().name</p>
})
}
Saya mendapatkan kesalahan yang mengatakan:
Baris 281: 23: Diharapkan penugasan atau panggilan fungsi dan bukannya melihat ekspresi tanpa-ekspresi yang tidak digunakan
Ketika saya mencoba:
{
this.props.firebase.db.collection('users').doc(authUser.uid).get("name")
.then(doc => {
console.log(doc.data().name),
<p>doc.data().name</p>
})
}
Pesan kesalahan mengatakan:
Diharapkan panggilan tugas atau fungsi dan bukannya melihat ekspresi
Saya siap untuk menyerah untuk mencari tahu cara mendapatkan permintaan snapshot agar berfungsi - jika saya bisa mendapatkan nama koleksi pengguna untuk ditampilkan di layar. Adakah yang bisa membantu dengan langkah itu?
PERIKSAAN BERIKUTNYA
Saya menemukan posting ini . Ini memiliki penjelasan yang baik tentang apa yang perlu terjadi, tetapi saya tidak dapat mengimplementasikannya seperti yang ditunjukkan karena componentDidMount tidak tahu apa itu authUser.
Upaya saya saat ini adalah sebagai berikut - namun, seperti yang saat ini ditulis, authUser adalah pembungkus nilai pengembalian - dan segmen componentDidMount tidak tahu apa itu authUser.
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);
PERIKSAAN BERIKUTNYA
Selanjutnya, saya mencoba membungkus rute untuk dashboard di dalam AuthContext.Consumer sehingga seluruh komponen dapat menggunakannya - dengan demikian membiarkan saya mengakses pengguna yang masuk dalam fungsi componentDidMount.
Saya mengubah rute ke:
<Route path={ROUTES.DASHBOARD} render={props => (
<AuthUserContext.Consumer>
{ authUser => (
<Dashboard authUser={authUser} {...props} />
)}
</AuthUserContext.Consumer>
)} />
dan menghapus konsumen dari pernyataan render komponen dasbor.
Kemudian di componentDidMount pada komponen Dashboard, saya mencoba:
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,
});
}
Ketika saya mencoba ini, saya mendapatkan kesalahan yang mengatakan:
FirebaseError: Function CollectionReference.doc () membutuhkan argumen pertamanya menjadi tipe string yang tidak kosong, tapi itu adalah: objek DocumentReference kustom
PERCOBAAN BERIKUTNYA Orang-orang di bawah ini sepertinya menemukan sesuatu yang bermanfaat dalam solusi yang diusulkan pertama. Saya belum dapat menemukan sesuatu yang berguna di dalamnya, tetapi membaca kembali saran-sarannya, saya berjuang untuk melihat bagaimana contoh dalam dokumentasi firebase (tidak mengungkapkan bagaimana memberikan: nilai uid ke permintaan .doc () ), yaitu sebagai berikut:
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!");
}
secara fundamental berbeda dengan upaya saya dalam fungsi componentDidMount, yaitu:
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");
}
);
}
Mungkin memecahkan langkah itu adalah petunjuk yang akan membantu untuk menggerakkan ini menuju hasil. Adakah yang bisa menemukan dokumentasi firestore yang lebih baik untuk menunjukkan cara mendapatkan catatan koleksi pengguna menggunakan pendengar pengguna yang masuk?
Untuk itu, saya dapat melihat dari contoh lab kode FriendlyEats , bahwa ada upaya untuk memberikan doc.id ke nilai pencarian id dalam kode. Saya tidak tahu bahasa apa kode ini ditulis - tetapi memang terlihat mirip dengan apa yang saya coba lakukan - saya hanya tidak bisa melihat bagaimana cara beralih dari contoh itu ke sesuatu yang saya tahu cara kerjanya.
display: function(doc) {
var data = doc.data();
data['.id'] = doc.id;
data['go_to_restaurant'] = function() {
that.router.navigate('/restaurants/' + doc.id);
};