Tôi đang cố gắng tìm ra cách lấy tên người dùng là thuộc tính được lưu trữ trong bộ sưu tập người dùng, đã được hợp nhất với các thuộc tính được tạo bởi mô hình xác thực firebase.
Tôi có thể truy cập authUser - cung cấp cho tôi các căn cứ hỏa lực giới hạn thu thập trong công cụ xác thực và sau đó tôi đang cố gắng chuyển từ đó đến bộ sưu tập người dùng liên quan (sử dụng cùng một uid).
Tôi có một người tiêu dùng bối cảnh phản ứng với:
import React from 'react';
const AuthUserContext = React.createContext(null);
export default AuthUserContext;
Sau đó, trong thành phần của tôi, tôi đang cố gắng sử dụng:
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);
Trong firebase.js của tôi - Tôi nghĩ rằng tôi đã cố gắng hợp nhất các thuộc tính authUser từ mô hình Xác thực với các thuộc tính bộ sưu tập người dùng như sau:
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();
}
});
Tôi không thể tìm cách lấy từ authUser (hoạt động để đưa tôi đến các thuộc tính Xác thực) - đến bộ sưu tập người dùng có id với cùng một uid từ bộ sưu tập Xác thực.
Tôi đã thấy bài đăng này , dường như có cùng một vấn đề và đã cố gắng tìm ra câu trả lời được cho là gợi ý - nhưng dường như tôi không thể tìm ra cách nào để chuyển từ bộ sưu tập Xác thực sang bộ sưu tập người dùng và tôi không biết hợp nhất đang làm gì cho tôi nếu nó không cho tôi quyền truy cập vào các thuộc tính trên bộ sưu tập người dùng từ authUser.
Tôi đã cố gắng sử dụng một trình trợ giúp trong firebase.js để cung cấp cho tôi một người dùng từ một uid - nhưng điều đó dường như cũng không giúp được gì.
user = uid => this.db.doc(`users/${uid}`);
users = () => this.db.collection('users');
Nỗ lực tiếp theo
Để thêm nền, tôi đã tạo một thành phần thử nghiệm có thể đăng nhập (nhưng không kết xuất) authUser, như sau:
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;
Nhật ký hiển thị chi tiết về uid, email, v.v. trong nhật ký, nhưng nó nằm trong một danh sách dài các mục - nhiều mục được mở đầu bằng 1 hoặc 2 chữ cái (Tôi không thể tìm thấy khóa để tìm ra mỗi tiền tố này chữ có nghĩa). Ví dụ được trích xuất dưới đây:
CẬP NHẬT VỀ NHẬN XÉT NÀY:
Trước đây, tôi đã nói: Các trường cho uid, email, v.v. dường như không được lồng bên dưới các tiền tố này, nhưng nếu tôi cố gắng:
console.log(authUser.email)
, Tôi nhận được một lỗi cho biết:
TypeError: Không thể đọc thuộc tính 'email' của null
Bản cập nhật: Tôi mới nhận ra rằng trong nhật ký giao diện điều khiển, tôi phải mở rộng menu thả xuống có nhãn:
Q {I: Mảng (0), l:
để xem thuộc tính email. Có ai biết những gì jibberish ám chỉ? Tôi không thể tìm thấy chìa khóa để tìm hiểu ý nghĩa của Q, tôi hoặc l, để biết liệu tôi có nên tham khảo những điều này để đến các thuộc tính có liên quan trong bảng Xác thực hay không. Có lẽ nếu tôi có thể tìm ra điều đó - tôi có thể tìm cách đến bộ sưu tập người dùng bằng cách sử dụng uid từ bộ sưu tập Xác thực.
Có ai đã sử dụng phản ứng ở mặt trước, với một người tiêu dùng bối cảnh để tìm ra người dùng hiện tại là ai chưa? Nếu vậy, làm thế nào để bạn truy cập các thuộc tính của chúng trên mô hình Xác thực và làm thế nào bạn truy cập các thuộc tính trên bộ sưu tập Người dùng liên quan (trong đó docId trên tài liệu Người dùng là uid từ bảng Xác thực)?
TIẾP THEO TIẾP THEO
Nỗ lực tiếp theo đã tạo ra một kết quả rất kỳ lạ.
Tôi có 2 trang riêng biệt là người tiêu dùng bối cảnh. Sự khác biệt giữa chúng là một cái là một hàm và cái kia là một thành phần lớp.
Trong thành phần chức năng, tôi có thể kết xuất {authUser.email}. Khi tôi cố gắng làm điều tương tự trong thành phần lớp, tôi gặp lỗi:
TypeError: Không thể đọc thuộc tính 'email' của null
Lỗi này đến từ cùng một phiên với cùng một người dùng đã đăng nhập.
Lưu ý: trong khi tài liệu về căn cứ hỏa lực nói rằng một thuộc tính hiện tại của Người dùng có sẵn trên auth - Tôi chưa thể làm cho nó hoạt động được.
Thành phần chức năng của tôi có:
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;
Mặc dù tôi không thể truy cập các thuộc tính bộ sưu tập Người dùng trong đó docId trên tài liệu người dùng giống với uid của người dùng được xác thực, từ thành phần này, tôi có thể xuất thuộc tính email trên bộ sưu tập auth cho người dùng này.
Mặc dù tài liệu Firebase cung cấp lời khuyên này để quản lý người dùng và truy cập các thuộc tính ở đây, tôi chưa tìm thấy cách nào để thực hiện phương pháp này trong phản ứng. Mỗi biến thể của một nỗ lực thực hiện việc này, cả bằng cách tạo các trình trợ giúp trong firebase.js của tôi và bằng cách cố gắng bắt đầu từ đầu trong một thành phần đều tạo ra lỗi khi truy cập firebase. Tuy nhiên tôi có thể tạo danh sách người dùng và thông tin bộ sưu tập Người dùng liên quan của họ (Tôi không thể có được người dùng dựa trên người dùng authUser).
Thành phần lớp học của tôi có:
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;
Trong AuthContext.Provider của tôi - Tôi có:
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;
TIẾP THEO TIẾP THEO
Điều thực sự kỳ lạ là với nỗ lực này, tôi đang cố gắng điều khiển ghi nhật ký các giá trị mà tôi có thể thấy tồn tại trong cơ sở dữ liệu và giá trị của tên được trả về là 'không xác định' trong đó db có một chuỗi trong đó.
Nỗ lực này có:
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);
TIẾP THEO TIẾP THEO
Vì vậy, nỗ lực này là vụng về và không sử dụng các trợ giúp hoặc các truy vấn chụp nhanh mà tôi đã cố gắng sử dụng ở trên, nhưng đăng nhập các thuộc tính tài liệu bộ sưu tập người dùng vào bảng điều khiển như sau:
{this.props.firebase.db.collection ('người dùng'). doc (authUser.uid) .get ()
.then(doc => {
console.log(doc.data().name)
})
}
Những gì tôi không thể làm là tìm cách hiển thị tên đó trong jsx
Làm thế nào để bạn thực sự in đầu ra?
Khi tôi cố gắng:
{
this.props.firebase.db.collection('users').doc(authUser.uid).get().data().name
}
Tôi nhận được một lỗi cho biết:
LoạiError: this.props.firebase.db.collection (...). Doc (...). Get (...). Dữ liệu không phải là một hàm
Khi tôi cố gắng:
{
this.props.firebase.db.collection('users').doc(authUser.uid).get()
.then(doc => {
console.log(doc.data().name),
<p>doc.data().name</p>
})
}
Tôi nhận được một lỗi cho biết:
Dòng 281: 23: Dự kiến một lệnh gán hoặc gọi hàm và thay vào đó thấy một biểu thức không có biểu thức không sử dụng
Khi tôi cố gắng:
{
this.props.firebase.db.collection('users').doc(authUser.uid).get("name")
.then(doc => {
console.log(doc.data().name),
<p>doc.data().name</p>
})
}
Thông báo lỗi cho biết:
Dự kiến một lệnh gọi hoặc hàm và thay vào đó đã thấy một biểu thức
Tôi đã sẵn sàng từ bỏ việc cố gắng tìm hiểu làm thế nào để các truy vấn chụp nhanh hoạt động - nếu tôi có thể lấy tên của bộ sưu tập người dùng để hiển thị trên màn hình. Bất cứ ai có thể giúp với bước đó?
TIẾP THEO TIẾP THEO
Tôi tìm thấy bài này . Nó có một lời giải thích tốt về những gì cần phải xảy ra, nhưng tôi không thể thực hiện nó như được hiển thị vì thành phầnDidMount không biết authUser là gì.
Nỗ lực hiện tại của tôi là như sau - tuy nhiên, như được viết hiện tại, authUser là một trình bao bọc trên giá trị trả về - và phân đoạn thành phầnDidMount không biết authUser là gì.
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);
TIẾP THEO TIẾP THEO
Tiếp theo, tôi đã thử gói tuyến đường cho bảng điều khiển bên trong AuthContext.Consumer để toàn bộ thành phần có thể sử dụng nó - do đó cho phép tôi truy cập người dùng đã đăng nhập trong hàm thành phầnDidMount.
Tôi đã thay đổi tuyến đường thành:
<Route path={ROUTES.DASHBOARD} render={props => (
<AuthUserContext.Consumer>
{ authUser => (
<Dashboard authUser={authUser} {...props} />
)}
</AuthUserContext.Consumer>
)} />
và loại bỏ người tiêu dùng khỏi câu lệnh kết xuất thành phần bảng điều khiển.
Sau đó, trong thành phầnDidMount trên thành phần Bảng điều khiển, tôi đã thử:
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,
});
}
Khi tôi thử điều này, tôi nhận được một lỗi cho biết:
FirebaseError: Function CollectionReference.doc () yêu cầu đối số đầu tiên của nó phải là kiểu chuỗi không trống, nhưng đó là: một đối tượng DocumentReference tùy chỉnh
ATTEMPT TIẾP THEO Những người dưới đây dường như tìm thấy điều gì đó hữu ích trong giải pháp đề xuất đầu tiên. Tôi không thể tìm thấy bất cứ điều gì hữu ích trong đó, nhưng đọc lại các đề xuất của nó, tôi đang cố gắng xem ví dụ trong tài liệu về căn cứ hỏa lực (nó không tiết lộ cách đưa ra giá trị: uid cho yêu cầu .doc () ), như sau:
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!");
}
về cơ bản là khác với nỗ lực của tôi trong hàm thành phầnDidMount, đó là:
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");
}
);
}
Có lẽ giải quyết bước đó là một đầu mối sẽ giúp đưa điều này đến một kết quả. Bất cứ ai cũng có thể tìm thấy bất kỳ tài liệu Firestore tốt hơn để hiển thị làm thế nào để có được một bản ghi bộ sưu tập người dùng bằng cách sử dụng một người nghe đã đăng nhập uid?
Cuối cùng, tôi có thể thấy từ ví dụ trong phòng thí nghiệm mã FriendlyEats , rằng có một nỗ lực để cung cấp doc.id cho giá trị tìm kiếm id trong mã. Tôi không biết mã này được viết bằng ngôn ngữ nào - nhưng nó trông giống với ngôn ngữ mà tôi đang cố gắng thực hiện - Tôi chỉ không thể thấy làm thế nào để chuyển từ ví dụ đó sang thứ mà tôi biết cách làm việc.
display: function(doc) {
var data = doc.data();
data['.id'] = doc.id;
data['go_to_restaurant'] = function() {
that.router.navigate('/restaurants/' + doc.id);
};