ฉันกำลังพยายามหาวิธีรับชื่อผู้ใช้ซึ่งเป็นคุณลักษณะที่เก็บไว้ในคอลเลกชันผู้ใช้ซึ่งถูกรวมเข้ากับคุณลักษณะที่สร้างขึ้นโดยรูปแบบการรับรองความถูกต้องของ firebase
ฉันสามารถเข้าถึง authUser - ซึ่งให้ฐานข้อมูล firefield ที่ จำกัด แก่ฉันในเครื่องมือการตรวจสอบความถูกต้องแล้วฉันก็พยายามที่จะได้รับจากที่นั่นไปยังคอลเลกชันผู้ใช้ที่เกี่ยวข้อง (ซึ่งใช้ uid เดียวกัน)
ฉันมีผู้บริโภคที่ตอบสนองต่อบริบทด้วย:
import React from 'react';
const AuthUserContext = React.createContext(null);
export default AuthUserContext;
จากนั้นในองค์ประกอบของฉันฉันพยายามที่จะใช้:
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);
ใน firebase.js ของฉัน - ฉันคิดว่าฉันได้พยายามรวมคุณลักษณะ authUser จากรูปแบบการตรวจสอบสิทธิ์ด้วยแอตทริบิวต์การรวบรวมผู้ใช้ดังนี้
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();
}
});
ฉันไม่สามารถหาวิธีรับจาก authUser (ซึ่งทำงานเพื่อให้ฉันไปยังแอตทริบิวต์การรับรองความถูกต้อง) - ไปยังคอลเลกชันผู้ใช้ที่มี ID ที่มี uid เดียวกันจากคอลเลกชันการรับรองความถูกต้อง
ฉันได้เห็นโพสต์นี้ซึ่งดูเหมือนว่าจะมีปัญหาเดียวกันและพยายามหาคำตอบที่ควรจะเป็นคำใบ้ - แต่ฉันไม่สามารถหาวิธีที่ได้ผลจากคอลเลกชันการรับรองความถูกต้องไปยังคอลเลกชันผู้ใช้ และฉันไม่รู้ว่าการผสานกำลังทำอะไรให้ฉันถ้าไม่ให้ฉันเข้าถึงคุณลักษณะในการรวบรวมผู้ใช้จาก authUser
ฉันพยายามใช้ผู้ช่วยใน firebase.js ของฉันเพื่อให้ผู้ใช้จาก uid - แต่นั่นก็ไม่ได้ช่วยอะไร
user = uid => this.db.doc(`users/${uid}`);
users = () => this.db.collection('users');
ความพยายามครั้งต่อไป
ในการเพิ่มพื้นหลังเพิ่มเติมฉันได้สร้างองค์ประกอบทดสอบที่สามารถบันทึก (แต่ไม่แสดงผล) authUser ดังนี้:
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;
บันทึกแสดงรายละเอียดของ uid อีเมลและอื่น ๆ ในบันทึก แต่อยู่ในรายการที่มีความยาวหลายรายการซึ่งส่วนใหญ่นำหน้าด้วยตัวอักษร 1 หรือ 2 ตัว (ฉันไม่สามารถหากุญแจเพื่อค้นหาว่าคำนำหน้าเหล่านี้แต่ละคำ หมายถึงตัวอักษร) ตัวอย่างที่แยกไว้ด้านล่าง:
อัปเดตตามความคิดเห็นนี้:
ก่อนหน้านี้ฉันพูดว่า: ฟิลด์สำหรับ uid, อีเมล ฯลฯ ไม่ปรากฏว่าซ้อนอยู่ใต้คำนำหน้าเหล่านี้ แต่ถ้าฉันพยายาม:
console.log(authUser.email)
ฉันได้รับข้อผิดพลาดที่แจ้งว่า:
TypeError: ไม่สามารถอ่าน 'อีเมล' ของ null ได้
การปรับปรุง: ฉันเพิ่งรู้ว่าในบันทึกของคอนโซลฉันต้องขยายเมนูแบบเลื่อนลงที่มีข้อความ:
Q {I: Array (0), l:
เพื่อดูคุณสมบัติอีเมล์ ไม่มีใครรู้ว่าสิ่งที่พูดพล่อยๆนี้หมายถึงอะไร ฉันไม่สามารถหากุญแจเพื่อค้นหาว่าฉันหมายถึงอะไรฉันควรจะอ้างอิงสิ่งเหล่านี้เพื่อไปยังแอตทริบิวต์ที่เกี่ยวข้องในตารางการรับรองความถูกต้องหรือไม่ บางทีถ้าฉันสามารถหาได้ - ฉันสามารถหาวิธีที่จะได้รับคอลเล็กชันผู้ใช้โดยใช้ uid จากคอลเลกชันการรับรองความถูกต้อง
มีใครใช้ปฏิกิริยาบนส่วนหน้ากับบริบทผู้บริโภคเพื่อค้นหาผู้ใช้ปัจจุบันคือใคร ถ้าเป็นเช่นนั้นคุณจะเข้าถึงคุณลักษณะของตนในรูปแบบการรับรองความถูกต้องได้อย่างไรและคุณเข้าถึงคุณลักษณะในคอลเลกชันผู้ใช้ที่เกี่ยวข้องได้อย่างไร (โดยที่ docId ในเอกสารผู้ใช้เป็น uid จากตารางการตรวจสอบสิทธิ์)
ความพยายามต่อไป
ความพยายามครั้งต่อไปให้ผลลัพธ์ที่แปลกมาก
ฉันมี 2 หน้าแยกต่างหากที่เป็นบริบทผู้บริโภค ความแตกต่างระหว่างพวกเขาคือหนึ่งคือฟังก์ชั่นและอื่น ๆ เป็นองค์ประกอบระดับ
ในองค์ประกอบของฟังก์ชั่นฉันสามารถแสดงผล {authUser.email} เมื่อฉันพยายามทำสิ่งเดียวกันในองค์ประกอบของคลาสฉันได้รับข้อผิดพลาดที่แจ้งว่า:
TypeError: ไม่สามารถอ่าน 'อีเมล' ของ null ได้
ข้อผิดพลาดนี้มาจากเซสชันเดียวกันกับผู้ใช้ที่เข้าสู่ระบบเดียวกัน
หมายเหตุ: ในขณะที่เอกสารฐานข้อมูล firebase บอกว่าคุณสมบัติผู้ใช้ปัจจุบันมีให้ใช้งานใน auth - ฉันไม่สามารถใช้งานได้เลย
องค์ประกอบฟังก์ชั่นของฉันมี:
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;
ในขณะที่ฉันไม่สามารถเข้าถึงแอตทริบิวต์การรวบรวมผู้ใช้ที่ docId ในเอกสารผู้ใช้เหมือนกับ uid ของผู้ใช้ที่ได้รับการรับรองความถูกต้องจากส่วนประกอบนี้ฉันสามารถส่งออกแอททริบิวต์อีเมลในการตรวจสอบสิทธิ์สำหรับผู้ใช้นี้
ในขณะที่เอกสารประกอบ Firebaseให้คำแนะนำสำหรับการจัดการผู้ใช้และการเข้าถึงคุณลักษณะที่นี่ฉันไม่พบวิธีที่จะใช้วิธีการนี้ในการตอบสนอง ทุกรูปแบบของความพยายามในการทำเช่นนี้โดยการช่วยใน firebase.js ของฉันและพยายามเริ่มจากศูนย์ในส่วนประกอบทำให้เกิดข้อผิดพลาดในการเข้าถึง firebase อย่างไรก็ตามฉันสามารถสร้างรายการผู้ใช้และข้อมูลการรวบรวมผู้ใช้ที่เกี่ยวข้องของพวกเขา (ฉันไม่สามารถรับผู้ใช้ตามที่ authUser คือใคร)
องค์ประกอบชั้นเรียนของฉันมี:
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;
ใน AuthContext.Provider ของฉัน - ฉันมี:
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;
ความพยายามต่อไป
มันแปลกจริงๆที่มีความพยายามนี้ฉันพยายามที่จะบันทึกค่าที่ฉันเห็นอยู่ในฐานข้อมูลและค่าของชื่อจะถูกส่งกลับเป็น 'ไม่ได้กำหนด' ที่ db มีสตริงอยู่ในนั้น
ความพยายามนี้มี:
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);
ความพยายามต่อไป
ดังนั้นความพยายามนี้จึงเงอะงะและไม่ได้ใช้ประโยชน์จากตัวช่วยหรือคิวรี่สแน็ปช็อตที่ฉันพยายามใช้ด้านบน แต่บันทึกแอ็ตทริบิวต์เอกสารการรวบรวมผู้ใช้ไปยังคอนโซลดังนี้:
{this.props.firebase.db.collection ('users'). doc (authUser.uid) .get ()
.then(doc => {
console.log(doc.data().name)
})
}
สิ่งที่ฉันทำไม่ได้คือหาวิธีสร้างชื่อใน jsx
คุณจะพิมพ์งานจริงได้อย่างไร
เมื่อฉันลอง:
{
this.props.firebase.db.collection('users').doc(authUser.uid).get().data().name
}
ฉันได้รับข้อผิดพลาดที่แจ้งว่า:
TypeError: this.props.firebase.db.collection (... ). doc (... ). รับ (... ) ข้อมูลไม่ใช่ฟังก์ชัน
เมื่อฉันลอง:
{
this.props.firebase.db.collection('users').doc(authUser.uid).get()
.then(doc => {
console.log(doc.data().name),
<p>doc.data().name</p>
})
}
ฉันได้รับข้อผิดพลาดที่แจ้งว่า:
บรรทัดที่ 281: 23: คาดว่าจะมีการมอบหมายหรือเรียกใช้ฟังก์ชันและแทนที่จะเห็นนิพจน์ที่ไม่ได้ใช้นิพจน์
เมื่อฉันลอง:
{
this.props.firebase.db.collection('users').doc(authUser.uid).get("name")
.then(doc => {
console.log(doc.data().name),
<p>doc.data().name</p>
})
}
ข้อความแสดงข้อผิดพลาดแจ้งว่า:
คาดว่าจะได้รับมอบหมายหรือเรียกฟังก์ชั่นและแทนที่จะเห็นการแสดงออก
ฉันพร้อมที่จะล้มเลิกความพยายามที่จะหาวิธีที่จะทำให้คิวรีสแน็ปช็อตทำงาน - ถ้าฉันสามารถรับชื่อคอลเลกชันของผู้ใช้ที่จะแสดงบนหน้าจอ ใครสามารถช่วยในขั้นตอนนั้นได้บ้าง
ความพยายามต่อไป
ฉันพบโพสต์นี้ มันมีคำอธิบายที่ดีเกี่ยวกับสิ่งที่ต้องเกิดขึ้น แต่ฉันไม่สามารถนำไปใช้ได้ดังที่แสดงเนื่องจาก componentDidMount ไม่ทราบว่า authUser คืออะไร
ความพยายามในปัจจุบันของฉันมีดังนี้ - อย่างไรก็ตามตามที่เขียนไว้ในปัจจุบัน authUser เป็น wrapper ของค่าส่งคืน - และเซ็กเมนต์ componentDidMount ไม่ทราบว่า 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);
ความพยายามต่อไป
ถัดไปฉันพยายามปิดเส้นทางสำหรับแดชบอร์ดภายใน AuthContext.Consumer เพื่อให้ส่วนประกอบทั้งหมดสามารถใช้งานได้ - ดังนั้นให้ฉันเข้าถึงผู้ใช้ที่ล็อกอินในฟังก์ชั่น componentDidMount
ฉันเปลี่ยนเส้นทางเป็น:
<Route path={ROUTES.DASHBOARD} render={props => (
<AuthUserContext.Consumer>
{ authUser => (
<Dashboard authUser={authUser} {...props} />
)}
</AuthUserContext.Consumer>
)} />
และลบคอนซูมเมอร์ออกจากคำสั่งการเรนเดอร์องค์ประกอบแดชบอร์ด
จากนั้นใน componentDidMount บนองค์ประกอบ Dashboard ฉันพยายาม:
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,
});
}
เมื่อฉันลองทำสิ่งนี้ฉันได้รับข้อผิดพลาดที่แจ้งว่า:
FirebaseError: Function CollectionReference.doc () ต้องการอาร์กิวเมนต์ตัวแรกที่ต้องเป็นสตริงที่ไม่ว่างเปล่า แต่มันเป็นวัตถุ DocumentReference แบบกำหนดเอง
ความพยายามครั้ง ต่อไปผู้คนด้านล่างดูเหมือนจะพบสิ่งที่มีประโยชน์ในโซลูชันแรกที่เสนอ ฉันไม่สามารถหาสิ่งที่มีประโยชน์ได้ แต่อ่านกลับผ่านคำแนะนำของฉันฉันดิ้นรนเพื่อดูว่าตัวอย่างในเอกสารประกอบ firebase (ไม่เปิดเผยวิธีการให้: uid ค่ากับคำขอ. doc () ) ซึ่งเป็นดังนี้:
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!");
}
ความแตกต่างกับความพยายามของฉันในฟังก์ชั่น componentDidMount ซึ่งก็คือ:
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");
}
);
}
บางทีการแก้ไขขั้นตอนนั้นเป็นเงื่อนงำที่จะช่วยในการย้ายไปสู่ผลลัพธ์ ทุกคนสามารถหาเอกสาร firestore ที่ดีกว่าเพื่อแสดงวิธีการรับบันทึกการรวบรวมผู้ใช้โดยใช้ฟังผู้ใช้ uid?
ด้วยเหตุนี้ฉันสามารถดูได้จากตัวอย่างการทดลองรหัส FriendlyEats ว่ามีความพยายามที่จะให้ doc.id กับค่าการค้นหา id ในรหัส ฉันไม่รู้ว่ารหัสนี้เขียนด้วยภาษาใด แต่ดูเหมือนว่าฉันกำลังพยายามทำอะไรฉันไม่เห็นว่าจะย้ายจากตัวอย่างนั้นไปยังสิ่งที่ฉันรู้วิธีการทำงานด้วย
display: function(doc) {
var data = doc.data();
data['.id'] = doc.id;
data['go_to_restaurant'] = function() {
that.router.navigate('/restaurants/' + doc.id);
};