火力基地反应:CollectionReference.doc()参数类型 [英] Firebase & React: CollectionReference.doc() argument type

查看:75
本文介绍了火力基地反应:CollectionReference.doc()参数类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试找出如何使用authUser uid作为文档ID在Firestore中查询记录.

I'm trying to figure out how to query a record in firestore using an authUser uid as the document id.

我已经看过这篇文章,并且正在尝试通过更新用户的状态来实现逻辑,以便componentDidMount函数可以在firestore的users集合中找到一个文档,该文档的ID与Authentication集合中的authUser.uid相同.

I have seen this post and am trying to implement the logic by updating the state of the user so that the componentDidMount function can find a document in the users collection in firestore, where that document has an id which is the same as the authUser.uid in the Authentication collection.

我有一个authListener,

I have an authListener with:

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 });
        },
      );
    }
    // componentDidMount() {
    //   this.listener = this.props.firebase.onAuthUserListener(
    //     /* next()     */ (authUserWithData) => this.setState({authUser: authUserWithData}),
    //     /* fallback() */ () => 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;

我的firebase配置文件定义了一个带有以下内容的助手:

My firebase config file defines a helper with:

onAuthUserListener(next, fallback) {
    // onUserDataListener(next, fallback) {
      return this.auth.onAuthStateChanged(authUser => {
        if (!authUser) {
          // user not logged in, call fallback handler
          fallback();
          return;
        }

        this.user(authUser.uid).get()
          .then(snapshot => {
            let snapshotData = snapshot.data();

            let userData = {
              ...snapshotData, // snapshotData first so it doesn't override information from authUser object
              uid: authUser.uid,
              email: authUser.email,
              emailVerified: authUser.emailVerifed,
              providerData: authUser.providerData
            };

            setTimeout(() => next(userData), 0); // escapes this Promise's error handler
          })
          .catch(err => {
            // TODO: Handle error?
            console.error('An error occured -> ', err.code ? err.code + ': ' + err.message : (err.message || err));
            setTimeout(fallback, 0); // escapes this Promise's error handler
          });
      });
    }

然后,在我要使用来自Cloud Firestore中相关用户集合的已登录用户属性的组件中,我有一个组件:

Then, in the component where I'm trying to use the logged in user's attributes from the related user collection in cloud firestore, I have a component with:

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, withAuthentication } from '../Session/Index';


const { Title, Text, Paragraph } = 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 is the current attempt -
  this.unsubscribe =
  this.props.firebase.db
    .collection('users')
    .doc(this.props.authUser.uid)
    .get()
    .then(doc => {
        this.setState({ name: doc.data().name });
        // loading: false,
      } 
      // else {
      //   // doc.data() will be undefined in this case
      //   console.log("Can't find this record");
      // }

    );  
  }                  



  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 (

        <div>    


                <Header>
                 <Text style={{ float: 'right', color: "#fff"}}>{this.state.authUser.uid}


                 {/* 

{this.props.firebase.db.collection('users').doc(authUser.uid).get()

      .then(doc => {
          console.log(doc.data().name) 
      })

    } 
                   { 
                    this.props.firebase.db.collection('users').doc(this.props.authUser.uid).get()
                    .then(doc => {
                        console.log("test", doc.data().name
)                          
                    })
                  } 

                  {console.log(this.props.user.email)}
                  */} 


        </div>

    );
  }
}

当我尝试在componentDidMount查询中使用authUser.uid时,出现错误消息:

When I try to use the authUser.uid in the componentDidMount query, I get an error that says:

FirebaseError:函数CollectionReference.doc()需要其第一个 参数为非空字符串,但它是:一个自定义 DocumentReference对象

FirebaseError: Function CollectionReference.doc() requires its first argument to be of type non-empty string, but it was: a custom DocumentReference object

此组件的路由包装在authUser Context.Consumer中:

The route for this component is wrapped in the authUser Context.Consumer:

 <Route path={ROUTES.DASHBOARD} render={props => (
          <AuthUserContext.Consumer>
             { authUser => ( 
                <Dashboard authUser={authUser} {...props} />  
             )}
          </AuthUserContext.Consumer>
        )} />

我可以使用doc id(即Authentication集合中的authUser uid)登录存储在用户集合中的属性-但我找不到将该authUser uid放入用户集合的firebase查询中的方法在componentDidMount函数中.

I can console.log the attributes stored in the user collection with the doc id which is the authUser uid in the Authentication collection - but I can't find a way to put that authUser uid into a firebase query on the users collection in the componentDidMount function.

我看过这篇文章暗示doc()值可以是字符串以外的其他值,但是这可能是计时问题,因为Firebase可能尚未在查询运行时识别出authUser.如果是这样,我在哪里可以在查询上放置一个等待标记来解决此问题?

I have seen this post which suggests that a doc() value can be something other than a string, but that it might be a timing problem in that firebase may not have identified the authUser by the point at which the query runs. If that's true, where can I put an await tag on the query to fix this problem?

我还看到了此帖子,这表明我需要进行构建以将authUser.uid转换为字符串,然后再将其提供给Firestore查询.这些响应中有几个表达了对了解文档ID是否可以是字符串以外的其他内容的兴趣.

I have also seen this post which suggests that I need to build a work around to convert the authUser.uid to a string before I give it to the firestore query. Several of those responses express interest in knowing if the doc id can be something other than a string.

推荐答案

我相信问题在于auth侦听器功能在auth对象出现之前就已运行.

I believe the problem is that the auth listener function is running before auth objects shows up.

解决这个问题的一种方法是撤销您的保护条款,所以...

One way around this is to reverse your guard clause, so...

 return this.auth.onAuthStateChanged(authUser => {
    if (authUser) {
      this.user(authUser.uid)
        .get()
        .then(snapshot => {...});
    }

    // user not logged in, call fallback handler
    fallback();
    return
  });

这篇关于火力基地反应:CollectionReference.doc()参数类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆