Firestore में किसी उपयोगकर्ता से संबंधित डीबी विवरण कैसे प्राप्त करते हैं?


10

मैं यह पता लगाने की कोशिश कर रहा हूं कि उपयोगकर्ता नाम कैसे प्राप्त किया जाए जो एक उपयोगकर्ता संग्रह में संग्रहीत विशेषता है, जिसे फायरबेस प्रमाणीकरण मॉडल द्वारा बनाई गई विशेषताओं के साथ मिला दिया गया है।

मैं तक पहुँच सकता है - जो मुझे सीमित उपकरण देता है फायरबस प्रमाणीकरण उपकरण में एकत्र करता है, और फिर मैं वहां से संबंधित उपयोगकर्ता संग्रह (जो उसी यूआईडी का उपयोग करता है) को प्राप्त करने की कोशिश कर रहा हूं।

मेरे पास एक प्रतिक्रिया संदर्भ उपभोक्ता है:

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 में - मुझे लगता है कि मैंने ऑथेंटिकेशन मॉडल से ऑस्ट्रियन मॉडल के ऑरिजनल गुण को मर्ज करने की कोशिश की है।

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();
      }
    });

मुझे उपयोगकर्ता संग्रह से प्राप्त करने का एक तरीका नहीं मिल सकता है (जो मुझे प्रमाणीकरण विशेषताओं पर ले जाने के लिए काम करता है) - उपयोगकर्ता संग्रह के लिए जो प्रमाणीकरण संग्रह से समान यूआईडी के साथ एक आईडी है।

मैंने इस पोस्ट को देखा है , जिसमें एक ही समस्या है और यह पता लगाने की कोशिश की गई है कि उत्तर क्या माना जाता है - लेकिन मुझे ऐसा तरीका नहीं मिल रहा है जो प्रमाणीकरण संग्रह से उपयोगकर्ता संग्रह तक पहुंचने के लिए काम करता हो और मुझे नहीं पता कि मेरे लिए क्या मर्ज है अगर यह मुझे उपयोगकर्ता संग्रह पर विशेषताओं का उपयोग करने की अनुमति नहीं दे रहा है।

मैंने अपने फायरबेस में एक सहायक का उपयोग करने की कोशिश की। मुझे एक यूआईडी से एक उपयोगकर्ता देने के लिए - लेकिन वह भी मदद नहीं करता है।

user = uid => this.db.doc(`users/${uid}`);
  users = () => this.db.collection('users');

अगला प्रयास

अधिक बैकग्राउंड जोड़ने के लिए, मैंने एक टेस्ट कंपोनेंट बनाया है जो लॉगऑन कर सकता है (लेकिन रेंडर नहीं)

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;

लॉग लॉग में यूआईडी, ईमेल आदि के लिए विवरण दिखाता है, लेकिन यह मदों की एक लंबी सूची के बीच है - जिनमें से कई 1 या 2 अक्षरों के साथ पूर्वनिर्मित हैं (मुझे पता लगाने के लिए एक कुंजी नहीं मिल सकती है कि इनमें से प्रत्येक उपसर्ग क्या है अक्षर का मतलब है)। नीचे दिया गया उदाहरण:

यहां छवि विवरण दर्ज करें

इस टिप्पणी पर अद्यतन:

इससे पहले, मैंने कहा: यूआईडी, ईमेल आदि के लिए फ़ील्ड इन उपसर्गों के नीचे नेस्टेड प्रतीत नहीं होते हैं, लेकिन अगर मैं इसके लिए प्रयास करता हूं:

 console.log(authUser.email)

, मुझे एक त्रुटि मिलती है जो कहती है:

TypeError: null की प्रॉपर्टी 'ईमेल' नहीं पढ़ सकता

अद्यतन: मुझे बस एहसास हुआ कि कंसोल लॉग में, मुझे एक ड्रॉप डाउन मेनू का विस्तार करना होगा जो लेबल है:

क्यू {I: एरे (0), एल:

ईमेल विशेषता देखने के लिए। क्या किसी को पता है कि इस जिबरिश का क्या मतलब है? मुझे यह पता करने के लिए कि Q, I या l का क्या मतलब है, यह जानने के लिए कि क्या मैं इन चीजों को संदर्भित करने वाला हूं, प्रमाणीकरण तालिका में प्रासंगिक विशेषताओं को प्राप्त करने के लिए एक कुंजी नहीं मिल सकती है। शायद अगर मैं यह पता लगा सकता हूं - मैं प्रमाणीकरण संग्रह से यूआईडी का उपयोग करके उपयोगकर्ता संग्रह के लिए एक रास्ता खोज सकता हूं।

क्या किसी ने उपभोक्ता के संदर्भ के साथ सामने के छोर पर प्रतिक्रिया का उपयोग किया है, यह पता लगाने के लिए कि वर्तमान उपयोगकर्ता कौन है? यदि हां, तो आप प्रमाणीकरण मॉडल पर उनकी विशेषताओं का उपयोग कैसे करते हैं और आपने संबंधित उपयोगकर्ता संग्रह पर विशेषताओं का उपयोग कैसे किया (जहां उपयोगकर्ता दस्तावेज़ पर docId प्रमाणीकरण तालिका से यूआईडी है)?

अगले ATTEMPT

अगले प्रयास ने एक बहुत ही अजीब परिणाम उत्पन्न किया है।

मेरे पास 2 अलग-अलग पृष्ठ हैं जो संदर्भ उपभोक्ता हैं। उनके बीच का अंतर यह है कि एक एक फ़ंक्शन है और दूसरा एक क्लास घटक है।

फ़ंक्शन घटक में, मैं {difUser.email} रेंडर कर सकता हूं। जब मैं कक्षा घटक में एक ही काम करने की कोशिश करता हूं, तो मुझे एक त्रुटि मिलती है जो कहती है:

TypeError: null की प्रॉपर्टी 'ईमेल' नहीं पढ़ सकता

यह त्रुटि उसी सत्र से आ रही है जिसमें लॉग इन उपयोगकर्ता है।

नोट: जबकि फायरबेस डॉक्यूमेंटेशन कहता है कि एक करंट संपत्ति प्रॉपर्टी पर उपलब्ध है - मुझे वह काम करने के लिए नहीं मिला है।

मेरे फ़ंक्शन घटक में है:

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 प्रमाणीकृत उपयोगकर्ता के यूआईडी के समान है, इस घटक से, मैं इस उपयोगकर्ता के लिए संग्रह पर ईमेल विशेषता को आउटपुट कर सकता हूँ।

जबकि फायरबेस प्रलेखन उपयोगकर्ताओं को प्रबंधित करने और विशेषताओं तक पहुंचने के लिए यह सलाह प्रदान करता है, मुझे प्रतिक्रिया में इस दृष्टिकोण को लागू करने का कोई तरीका नहीं मिला है। ऐसा करने के प्रयास का प्रत्येक रूपांतर, मेरे फायरबेस में सहायक बनाने से दोनों और घटक में खरोंच से शुरू करने की कोशिश करने से फायरबेस तक पहुंचने में त्रुटियां पैदा होती हैं। हालांकि मैं उपयोगकर्ताओं की सूची और उनके संबंधित उपयोगकर्ता संग्रह की जानकारी का उत्पादन कर सकता हूं (मुझे कोई उपयोगकर्ता नहीं मिल सकता है, जो इस बात पर आधारित हो कि कौन-कौन से उपयोगकर्ता हैं)।

मेरे वर्ग के घटक हैं:

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;

अगले ATTEMPT

यह वास्तव में अजीब है कि इस प्रयास के साथ, मैं उन मूल्यों को सांत्वना देने की कोशिश कर रहा हूं, जिन्हें मैं डेटाबेस में मौजूद देख सकता हूं और नाम के मूल्य को 'अपरिभाषित' के रूप में वापस किया जा रहा है, जहां डीबी में एक स्ट्रिंग है।

इस प्रयास में है:

    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);

अगले ATTEMPT

तो यह प्रयास अनाड़ी है और मददगारों या स्नैपशॉट प्रश्नों का उपयोग नहीं करता है जो मैंने ऊपर उपयोग करने की कोशिश की थी, लेकिन उपयोगकर्ता संग्रह दस्तावेज़ विशेषताओं को कंसोल में लॉग इन करें:

{this.props.firebase.db.collection ('उपयोगकर्ता')। doc (difUser.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 ((...) डेटा एक फ़ंक्शन नहीं है।

जब मैं कोशिश करता हूं:

{ 



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>
              })
            }

त्रुटि संदेश कहता है:

एक असाइनमेंट या फ़ंक्शन कॉल की अपेक्षा की और एक अभिव्यक्ति देखी

मैं यह जानने की कोशिश करने के लिए तैयार हूं कि स्नैपशॉट प्रश्नों को कैसे प्राप्त किया जाए - अगर मैं स्क्रीन पर प्रस्तुत करने के लिए उपयोगकर्ता संग्रह का नाम प्राप्त कर सकता हूं। क्या कोई उस कदम से मदद कर सकता है?

अगले ATTEMPT

मुझे यह पोस्ट मिली । इसकी एक अच्छी व्याख्या है कि क्या होने की आवश्यकता है, लेकिन मैं इसे लागू नहीं कर सकता जैसा कि दिखाया गया है क्योंकि ComponentsDidMount को यह पता नहीं है कि ओटेरयूज़र क्या है।

मेरा वर्तमान प्रयास इस प्रकार है - हालांकि, जैसा कि वर्तमान में लिखा गया है, ऑर्टयूज़र रिटर्न वैल्यू पर एक आवरण है - और कंपोनेंटडिमाउंट सेगमेंट को यह नहीं पता है कि ऑक्ट्योर क्या है।

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);

अगले ATTEMPT

अगला, मैंने AuthContext.Consumer के अंदर डैशबोर्ड के लिए मार्ग को लपेटने का प्रयास किया ताकि पूरा घटक इसका उपयोग कर सके - जिससे मुझे घटकडाउन फ़ंक्शन में लॉग इन उपयोगकर्ता तक पहुंचने की सुविधा मिल सकती है।

मैंने इसका मार्ग बदल दिया है:

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

और डैशबोर्ड घटक रेंडर स्टेटमेंट से उपभोक्ता को हटा दिया।

तब डैशबोर्ड घटक पर कंपोनेंटमाउंट में, मैंने कोशिश की:

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 () को गैर-रिक्त स्ट्रिंग के प्रकार के पहले तर्क की आवश्यकता होती है, लेकिन यह था: एक कस्टम डॉक्यूमेंट संदर्भ वस्तु

अगले ATTEMPT नीचे दिए गए लोगों को पहले प्रस्तावित समाधान में कुछ उपयोगी लगता है। मैं इसमें कुछ भी उपयोगी नहीं पा रहा हूं, लेकिन अपने सुझावों के माध्यम से वापस पढ़ रहा हूं, मैं यह देखने के लिए संघर्ष कर रहा हूं कि फायरबेस डॉक्यूमेंटेशन में उदाहरण कैसे है (यह खुलासा नहीं करता है: .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!");
      }

घटकडाइम समारोह में मेरे प्रयास के लिए मौलिक रूप से भिन्न है, जो है:

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");
      }

    );  
  }

शायद उस कदम को हल करना एक सुराग है जो इसे एक परिणाम की ओर ले जाने में मदद करेगा। क्या कोई भी बेहतर फायरस्टार प्रलेखन पा सकता है यह दिखाने के लिए कि उपयोगकर्ता श्रोता यूआईडी में लॉग का उपयोग करके उपयोगकर्ता संग्रह रिकॉर्ड कैसे प्राप्त करें?

उस अंत तक, मैं फ्रेंडलीएट्स कोड लैब उदाहरण से देख सकता हूं कि कोड में आईडी खोज मूल्य के लिए एक doc.id देने का प्रयास है। मुझे नहीं पता कि यह कोड किस भाषा में लिखा गया है - लेकिन यह वही दिखता है जो मैं करने की कोशिश कर रहा हूं - मैं सिर्फ यह नहीं देख सकता कि उस उदाहरण से उस चीज़ तक कैसे जाया जाए जिसे मैं जानता हूं कि कैसे काम करना है।

display: function(doc) {
      var data = doc.data();
      data['.id'] = doc.id;
      data['go_to_restaurant'] = function() {
        that.router.navigate('/restaurants/' + doc.id);
      };

FYI करें आपकी शब्दावली बिल्कुल सही नहीं है, और इस प्रश्न को पढ़ना मुश्किल बना रहा है। फायरबेस में कुछ भी नहीं है जिसे "टेबल" कहा जाता है। फायरबेस प्रामाणिक में, केवल उपयोगकर्ता हैं - कोई "प्रमाणीकरण तालिका" नहीं। फायरस्टार में, उन संग्रहों के भीतर संग्रह, और दस्तावेज हैं, लेकिन कोई तालिका नहीं है। मैं यह पता लगाने की कोशिश कर रहा हूं कि आप कहां फंस रहे हैं और आपने जो कोड दिखाया है वह आपकी अपेक्षा के अनुरूप काम नहीं करता है, लेकिन मैं इसे एक साथ नहीं जोड़ रहा हूं। अधिक मानक शब्दावली का उपयोग करने के लिए प्रश्न का संपादन करने पर विचार करें जो आप डॉक्स को पाएंगे, और जो आप अपेक्षा के अनुरूप काम नहीं कर रहे हैं उसके बारे में अधिक स्पष्ट रहें।
डग स्टीवेंसन

ठीक - संग्रह के लिए स्थानापन्न तालिकाओं के लिए खुश। बात अभी भी वही है।
मेल

मेरा मुख्य मुद्दा यह है कि मैं वास्तव में आपकी बात नहीं कर सका, और शब्दावली ने मदद नहीं की। क्या आप अधिक विस्तार से बता सकते हैं कि आपके द्वारा दिखाए गए कोड में क्या काम नहीं करता है? क्या कुछ उम्मीद के मुताबिक काम नहीं हुआ? किसी भी त्रुटि या डिबग लॉग को वर्णन करने के लिए?
डग स्टीवेंसन

कुछ भी काम नहीं करता है। मैं उपयोगकर्ता संग्रह विवरण श्रोता से उपयोगकर्ता संग्रह तक पहुंचने का रास्ता खोजने की उम्मीद कर रहा हूं। ऑर्टयूज़र को संदर्भ हैंडलर और संबंधित वर्ग विधि में परिभाषित किया गया है जो विधि में परिवर्तन के लिए सुनता है। मैं प्रमाणीकरण संग्रह में विशेषताओं को नहीं पा सकता हूं - मैं फायरस्टार में संबंधित उपयोगकर्ता संग्रह तक पहुंचने की कोशिश कर रहा हूं। कोई लॉग नहीं। बस त्रुटि संदेश जो कहता है कि क्षेत्र अपरिभाषित है।
मेल

1
मेरा सुझाव है कि एक सरल कार्य के साथ शुरू करें, यह प्राप्त करें कि कुछ अनुभव प्राप्त करने के लिए काम करें, फिर इसे लागू करें जैसे कि आपके पास अब और अधिक जटिल समस्याएं। प्रलेखन के बारे में मौलिक रूप से कुछ भी गलत नहीं है (मुझे पता है, क्योंकि मैं हर समय इसका उपयोग करता हूं, और मैं उसी के साथ लोगों की मदद करता हूं)। स्टैक ओवरफ्लो पर मदद पाने के लिए, आपको एक विशिष्ट समस्या को स्पष्ट करने की आवश्यकता होगी, आदर्श रूप से एक MCVE जिसे कोई भी समस्या को पुन: उत्पन्न करने के लिए उपयोग कर सकता है। सिर्फ यह कहना कि "मैं इसे काम नहीं कर सकता" पर्याप्त नहीं है। stackoverflow.com/help/minimal-reproducible-example
डग स्टीवेंसन

जवाबों:


5

मैं आपके प्रश्न की अंतिम पंक्ति ( users = () => this.db.collection('users');) से समझता हूं कि संग्रह जहां आप उपयोगकर्ताओं पर अतिरिक्त जानकारी संग्रहीत करते हैं, उसे कहा जाता है usersऔर इस संग्रह में एक उपयोगकर्ता दस्तावेज़ उपयोगकर्ता (यूआईडी) को docId के रूप में उपयोग करता है।

निम्नलिखित को चाल (निष्कलंक) करनी चाहिए:

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.db.collection('users').doc(authUser.uid)
              .get()
              .then(snapshot => {
                const userData = snapshot.data();
                console.log(userData);
                //Do whatever you need with userData
                //i.e. merging it with authUser
                //......

                next(authUser);
          });
      } else {
        fallback();
      }
    });

इसलिए, onAuthStateChanged()विधि के माध्यम से निर्धारित पर्यवेक्षक के भीतर , जब हम पता लगाते हैं कि उपयोगकर्ता (यानी में if (authUser) {}) साइन इन है , तो हम संग्रह uidमें इस उपयोगकर्ता के अनुरूप अद्वितीय दस्तावेज़ को क्वेरी करने के लिए इसका उपयोग करते usersहैं (देखें एक दस्तावेज़ पढ़ें , और डॉक्टर get()तरीका)।


तो क्या मेरे द्वारा onAuthUserListener को परिभाषित करने के तरीके में कुछ गड़बड़ है? फिर अगर मैं आपके संशोधन को उस तरीके से आज़माता हूँ, तो मुझे क्या करना होगा कि मुझे उपयोगकर्ता संग्रह से प्राप्त करने के लिए क्या करना है?
मेल

"तो क्या मैं onAuthUserListener को परिभाषित करने के तरीके में कुछ गड़बड़ है?" -> वह नहीं जो मैं देख सकता हूं। "मुझे उपयोगकर्ता संग्रह से उपयोगकर्ता संग्रह में लाने के लिए क्या करना चाहिए?" -> अगर मैं सही ढंग से समझता हूं कि आप वन दस्तावेज़ प्राप्त करना चाहते हैं, तो संग्रह नहीं। जवाब में कोड काम करना चाहिए।
रेनॉड टार्नेक

मैं ओटेरूज़र प्राप्त करना चाहता हूं - क्या आपके कोड मेरे प्रयास पर सुधार है? मुझे वह तरीका नहीं मिल रहा है जो मुझे उसी संग्रह के लिए उपयोगकर्ता संग्रह तक पहुँच प्रदान करने के लिए ऑउटपुट प्राप्त करने के लिए काम करता हो, जिसमें एक ही यूआईडी हो। मैं आपके कोड सुझाव को समझने की कोशिश कर रहा हूं - कि पहले कदम के रूप में मेरा सुधार कैसे हो। कृपया आप पहचान सकते हैं कि इसमें से कौन सा सुधार / सुधार है? साभार
मेल

यदि आप करते हैं तो क्या होता है this.auth.onAuthStateChanged(authUser => { if (authUser) {console.log(authUser.uid) })?
रेनॉड तारनेक

मैं सभी ओटेरूज़र गुण (प्रमाणीकरण संग्रह डेटा) को आउटपुट कर सकता हूं। मैं यूजर कलेक्शन में संबंधित डॉक्यूमेंट से यूजर्स का डेटा नहीं ले सकता, जिसमें यूआईडी आईडी के रूप में है
मेल

1

मेरे पास एक सिद्धांत है जो मैं आपको परीक्षण करना चाहता हूं।

मुझे लगता है कि जब आप next(authUser)अपने onAuthStateChangedहैंडलर के अंदर कॉल कर रहे होते हैं , तो निष्पादन के दौरान यह एक त्रुटि (जैसे cannot read property 'name' of undefined at ...) से सामना करता है ।

आपका कोड अपेक्षा के अनुरूप काम नहीं कर रहा है क्योंकि आप जहां कॉल करते हैं next(authUser), वह then()एक प्रॉमिस चेन के अंदर होता है । प्रॉमिस के अंदर फेंकी गई कोई भी त्रुटि पकड़ी जाएगी और प्रोमिस को अस्वीकार कर दिया जाएगा। जब एक वादा खारिज कर दिया जाता है, तो इसे त्रुटि के साथ संलग्न त्रुटि हैंडलर कहेंगे। सवाल में वादा श्रृंखला वर्तमान में ऐसी कोई त्रुटि हैंडलर नहीं है।

यदि मैंने आपको खो दिया है, तो इस ब्लॉग पोस्ट के लिए एक प्रॉमिस क्रैश कोर्स के लिए पढ़ें और फिर वापस आएं।

तो ऐसी स्थिति से बचने के लिए हम क्या कर सकते हैं? प्रॉमिस हैंडलर के दायरे से next(authUser) बाहर कॉल करना सबसे सरल होगा then()। हम इसका उपयोग कर सकते हैं window.setTimeout(function)

तो आपके कोड में, आप प्रतिस्थापित करेंगे

next(authUser)

साथ में

setTimeout(() => next(authUser))
// or setTimeout(() => next(authUser), 0) for the same result

यह प्रॉमिस चेन द्वारा पकड़े जाने के बजाय किसी भी त्रुटि को सामान्य रूप से फेंक देगा।

महत्वपूर्ण बात, आपको एक कैच हैंडलर नहीं मिला है जो userDocRef.get()विफल होने पर संभालता है। तो बस जोड़ने .catch(() => setTimeout(fallback))के अंत पर then()अपने कोड फ़ॉलबैक विधि अगर यह त्रुटियों का उपयोग करता है तो।

तो हम साथ समाप्त करते हैं:

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 = {
      ...dbUser, // CHANGED: Moved dbUser to beginning so it doesn't override other info
      uid: authUser.uid,
      email: authUser.email,
      emailVerified: authUser.emailVerified,
      providerData: authUser.providerData
    };
    setTimeout(() => next(authUser), 0); // invoke callback outside of Promise
  })
  .catch((err) => setTimeout(() => fallback(), 0)); // invoke callback outside of Promise

संपादित कोड

उपरोक्त स्पष्टीकरण से आपको अपना कोड ठीक करने की अनुमति मिल सकती है, लेकिन यहां Firebaseविभिन्न आसानी से उपयोग में बदलाव के साथ आपकी कक्षा का मेरा संस्करण है ।

उपयोग:

import FirebaseHelper from './FirebaseHelper.js';

const fb = new FirebaseHelper();
fb.onUserDataListener(userData => {
  // do something - user is logged in!
}, () => {
  // do something - user isn't logged in or an error occurred
}

वर्ग परिभाषा:

// granular Firebase namespace import
import firebase from 'firebase/app';
import 'firebase/auth';
import 'firebase/firestore';

const config = { /* firebase config goes here */ };

export default class FirebaseHelper { // renamed from `Firebase` to prevent confusion
  constructor() {
    /* init SDK if needed */
    if (firebase.apps.length == 0) { firebase.initializeApp(config); }

    /* helpers */
    this.fieldValue = app.firestore.FieldValue;

    /* Firebase APIs */
    this.auth = firebase.auth();
    this.db = firebase.firestore();
  }

  getUserDocRef(uid) { // renamed from `user`
    return this.db.doc(`users/${uid}`);
  }

  getUsersColRef() { // renamed from `users`
    return this.db.collection('users');
  }

  /**
   * Attaches listeners to user information events.
   * @param {function} next - event callback that receives user data objects
   * @param {function} fallback - event callback that is called on errors or when user not logged in
   *
   * @returns {function} unsubscribe function for this listener
   */
  onUserDataListener(next, fallback) {
    return this.auth.onAuthStateChanged(authUser => {
      if (!authUser) {
        // user not logged in, call fallback handler
        fallback();
        return;
      }

      this.getUserDocRef(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('Error while getting user document -> ', err.code ? err.code + ': ' + err.message : (err.message || err));
          setTimeout(fallback, 0); // escapes this Promise's error handler
        });
    });
  }

  // ... other methods ...
}

ध्यान दें कि इस संस्करण में, onUserDataListenerविधि से सदस्यता समाप्त फ़ंक्शन लौटाता है onAuthStateChanged। जब आपका घटक अनमाउंट हो जाता है, तो आपको किसी भी प्रासंगिक श्रोता को अलग करना चाहिए ताकि आपको स्मृति रिसाव न हो या जब इसकी आवश्यकता न हो तो पृष्ठभूमि में चल रहे कोड को तोड़ दिया जाए।

class SomeComponent {
  constructor() {
    this._unsubscribe = fb.onUserDataListener(userData => {
      // do something - user is logged in!
    }, () => {
      // do something - user isn't logged in or an error occurred
    };
  }

  // later
  componentWillUnmount() {
    this._unsubscribe();
  }
}

धन्यवाद! मैं आज रात यह कोशिश करूँगा। मैं इसके बारे में जानने के लिए उत्साहित हूं। मैं प्रतिक्रिया के साथ शीघ्र ही वापस आऊंगा।
मेल

हाय सैम - इस सुझाव की पेशकश करने के लिए धन्यवाद। मैंने आपके द्वारा लिंक किए गए दस्तावेज़ के माध्यम से पढ़ने के लिए कुछ समय लिया और मैंने इस पर कुछ लिखा है। जबकि मैं मदद के लिए आभारी हूँ - इससे मेरी समस्या हल नहीं हुई। जब मैं उपयोगकर्ता संग्रह विशेषताओं को एक्सेस करने का प्रयास करता हूं, तो मुझे अभी भी एक त्रुटि मिल रही है जो कहती है: TypeError: अपरिभाषित की संपत्ति 'उपयोगकर्ता' नहीं पढ़ सकता है
मेल

@Mel जब आपने मूल कोड चलाया, तो क्या आपको TypeError के बारे में सूचित किया गया था? यह पहली बार है जब आपने इसका उल्लेख किया है। इसका मतलब है कि इस कोड ने प्रोमिस के दायरे से बाहर त्रुटि को फेंकने का काम किया। आप का उत्पादन प्रदान कर सकते हैं console.log(snapshot.data())?
समथेकिंगमैन

मैंने यह कोशिश की - त्रुटि संदेश कहता है: TypeError: snapshot.data कोई फ़ंक्शन नहीं है
मेल

मैं इसे इधर-उधर ले जाने की कोशिश करता रहूँगा - शायद मैं इसे अच्छे स्थान पर लॉग इन करने की कोशिश नहीं कर रहा हूँ
मेल

0

आपके AuthContext.Providerकार्यान्वयन में, आप onAuthStateChanged सीधे SDK के श्रोता तक पहुँचते हैं:

componentDidMount() {
  this.listener = this.props.firebase.auth.onAuthStateChanged(
    authUser => {
      authUser
        ? this.setState({ authUser })
        : this.setState({ authUser: null });
    }
  );
}

इसे onAuthUserListenerआपके सहायक वर्ग से उपयोग करने के लिए बदला जाना चाहिए :

componentDidMount() {
  this.listener = this.props.firebase.onAuthUserListener(
    /* next()     */ (authUserWithData) => this.setState({authUser: authUserWithData}),
    /* fallback() */ () => this.setState({authUser: null})
  );
}

बहुत सारे यादृच्छिक गुणों से भरे लॉग संदेशों के बारे में, इसका कारण यह है कि firebase.Userऑब्जेक्ट में एक सार्वजनिक एपीआई और कई निजी संपत्तियों और विधियों के साथ कार्यान्वयन होता है जो संकलित होने पर निर्धारित होते हैं। क्योंकि इन खनन योग्य गुणों और विधियों को स्पष्ट रूप से गणना योग्य नहीं के रूप में चिह्नित किया गया है, वे किसी भी लॉग आउटपुट में शामिल हैं। यदि आप इसके बजाय केवल उन हिस्सों को लॉग इन करना चाहते हैं जो वास्तव में उपयोगी हैं, तो आप उपयोग की गई वस्तु को नष्ट कर सकते हैं और उसका पुनर्गठन कर सकते हैं:

// Extracts public properties of firebase.User objects
// see https://firebase.google.com/docs/reference/js/firebase.User#properties
function extractPublicProps(user) {
  let {displayName, email, emailVerified, isAnonymous, metadata, phoneNumber, photoURL, providerData, providerId, refreshToken, tenantId, uid} = user;
  return {displayName, email, emailVerified, isAnonymous, metadata, phoneNumber, photoURL, providerData, providerId, refreshToken, tenantId, uid}
}

function extractUsefulProps(user) {
  let {displayName, email, emailVerified, isAnonymous, phoneNumber, photoURL, uid} = user;
  return {displayName, email, emailVerified, isAnonymous, phoneNumber, photoURL, uid}
}

let authUser = firebase.auth().currentUser;
console.log(authUser);
console.log(extractPublicProps(authUser));
console.log(extractUsefulProps(authUser));

मेरी मदद करने की कोशिश जारी रखने के लिए धन्यवाद @samthecodingman। इस पर मेरी नजर थी। मेरा उद्देश्य ओटेरयूज़र के यूआईडी को पढ़ना है ताकि मैं इसका उपयोग उस उपयोगकर्ता के लिए संबंधित उपयोगकर्ता संग्रह की विशेषताओं को प्राप्त करने के लिए कर सकूं। प्रमाणीकरण तालिका के गुण पढ़ें।
मेल

श्रोता कंपोनेंटडीडमाउंट फंक्शन में सुझाए गए बदलाव में कोई त्रुटि नहीं थी - लेकिन यह काम नहीं किया। जब यह श्रोता का उपयोग करके डैशबोर्ड घटक में ऑक्टिट्यूसर के मान को लॉग करने का प्रयास करता है - मुझे एक त्रुटि मिलती है जिसमें कहा गया है कि ऑक्ट्योर को परिभाषित नहीं किया गया है। मुझे यह त्रुटि नहीं मिलती है जब मैं AuthDontext.Provider के लिए कंपोनेंटडिमाउंट का उपयोग उस तरीके से करता हूं जिस तरह से मैंने इसे परिभाषित किया था। लॉग संदेशों में यादृच्छिक गुणों के बारे में जानकारी के लिए धन्यवाद।
मेल

@ मेल आप इस बात की पुष्टि कर सकते हैं कि आपकी Dashboardफ़ाइल की अंतिम पंक्ति export default withAuthentication(Dashboard);(और नहीं withFirebase) है
samthecodingman

की पुष्टि। withFirebase को withAuthentication में शामिल किया गया है - इसलिए यह उस HOC के माध्यम से उठाया जाता है।
मेल

@ मेल आप मैसेज भेज सकते हैं कि मैंने आपको
Slack

0

अगर किसी और को भी इसी तरह से अटका हुआ है, तो मुझे यहाँ समाधान मिला: Firebase & React: CollectionReference.doc () तर्क प्रकार

यह पेज रिफ्रेश पर काम नहीं करता है (फिर भी एक त्रुटि है कि यूआईडी अशक्त है) लेकिन प्रतिक्रिया का उपयोग करने के लिए हुक लगाता है कि माउंट और अपडेट के संयोजन के साथ कंपोनेंटमाउंट फ़ंक्शन को बदलना चाहिए। मैं कोशिश कर रहा हूँ कि अगले।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.