我试图弄清楚如何获取用户名,该用户名是存储在用户集中的属性,该用户集中已与firebase身份验证模型创建的属性合并。
我可以访问authUser-在身份验证工具中为firebase提供了有限的字段,然后尝试从那里转到相关的用户集合(使用相同的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中-我认为我尝试将Authentication模型中的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(可以使我进入Authentication属性)到用户集合的方法,该用户集合的ID与Authentication集合中的uid相同。
我看过这篇文章,似乎也有同样的问题,并试图找出答案应该暗示的内容-但我似乎找不到找到一种方法来从Authentication集合传递到user集合而且我不知道合并对我有什么作用,如果合并不能使我从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,email等的详细信息,但是它位于一长串的项目中-其中许多以1或2个字母开头(我找不到找到每个前缀的键字母意思)。示例摘录如下:
此评论的更新:
之前,我说过:uid,email等字段似乎未嵌套在这些前缀下,但是如果我尝试执行以下操作:
console.log(authUser.email)
,我看到一条错误消息:
TypeError:无法读取null的属性“ email”
更新: 我刚刚意识到,在控制台日志中,我必须展开一个带有标签的下拉菜单:
Q {I:Array(0),l:
查看电子邮件属性。有人知道这个低调的暗示吗?我找不到找出Q,I或l含义的密钥,以了解是否应该参考这些内容以获取Authentication表中的相关属性。也许我能弄清楚-我可以找到一种使用Authentication集合中的uid进入用户集合的方法。
有没有人在前端与上下文使用者互动,以找出当前用户是谁?如果是这样,您如何访问它们在身份验证模型上的属性以及如何访问相关的用户集合的属性(其中,用户文档上的docId是身份验证表中的uid)?
下次尝试
下次尝试产生了非常奇怪的结果。
我有2个单独的页面是上下文使用者。它们之间的区别在于,一个是函数,另一个是类组件。
在功能组件中,我可以呈现{authUser.email}。当我尝试在类组件中执行相同的操作时,出现错误消息:
TypeError:无法读取null的属性“ email”
此错误来自与同一登录用户相同的会话。
注意:虽然Firebase文档说auth上有currentUser属性可用,但我根本无法使它正常工作。
我的功能组件有:
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相同的User集合属性,但可以从此组件中输出该用户在auth集合上的email属性。
尽管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;
下次尝试
确实很奇怪,通过这种尝试,我试图以控制台方式记录我可以看到的数据库中存在的值,并且name的值作为“未定义”返回,其中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(...)。get(...)。data不是函数
当我尝试:
{
this.props.firebase.db.collection('users').doc(authUser.uid).get()
.then(doc => {
console.log(doc.data().name),
<p>doc.data().name</p>
})
}
我收到一条错误消息:
Line 281:23:期望分配或函数调用,而是看到一个表达式no-unused-expressions
当我尝试:
{
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是返回值的包装器-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);
下次尝试
接下来,我尝试将dashboard的路由包装在AuthContext.Consumer中,以便整个组件都可以使用它-从而使我可以在componentDidMount函数中访问登录的用户。
我将路线更改为:
<Route path={ROUTES.DASHBOARD} render={props => (
<AuthUserContext.Consumer>
{ authUser => (
<Dashboard authUser={authUser} {...props} />
)}
</AuthUserContext.Consumer>
)} />
并将使用者从仪表板组件的render语句中删除。
然后在Dashboard组件上的componentDidMount中,我尝试了:
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:函数CollectionReference.doc()要求其第一个参数的类型为非空字符串,但它是:一个自定义DocumentReference对象
下一个尝试 以下人似乎在第一个建议的解决方案中找到了有用的东西。我一直无法找到有用的东西,但是请仔细阅读其建议,我正在努力查看Firebase文档中的示例(它没有披露如何为.doc()请求提供:uid值) ),如下所示:
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搜索值。我不知道此代码是用什么语言编写的-但它确实与Im试图执行的操作类似-我只是看不到如何从该示例过渡到我知道如何使用的语言。
display: function(doc) {
var data = doc.data();
data['.id'] = doc.id;
data['go_to_restaurant'] = function() {
that.router.navigate('/restaurants/' + doc.id);
};