首页 > 解决方案 > 在 React 中何时何地检查 Firebase 用户

问题描述

我想弄清楚如何使用 Firebase。

我有一个带有身份验证侦听器的配置:

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

    // ... other methods ...
  // }  

我已阅读有关创建侦听器的文档以查看是否有 authUser 并已插入此身份验证侦听器。

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;

然后在消费者组件中我有:

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,
  };




  onCollapse = collapsed => {
    console.log(collapsed);
    this.setState({ collapsed });
  };

  render() {



    return (
    <AuthUserContext.Consumer>
      { authUser => (  

        <div>    

                 <Text style={{ float: 'right', color: "#fff"}}>
                 {/* 
                    { 
                      this.props.firebase.db.collection('users').doc(authUser.uid).get()
                      .then(doc => {
                          console.log( doc.data().name
)                          
                      })
                    } 
                  */} 

        </div>
      )}
    </AuthUserContext.Consumer>  
    );
  }
}

export default withFirebase(Dashboard);

第一次加载页面时它工作正常。

但是,在页面刷新时,系统比代码慢并返回 null 错误消息,内容如下:

TypeError:无法读取 null 的属性“uid”(匿名函数)

我看过这篇文章,它提出了 Angular 的解决方案。

我找不到实现这一点的方法,以便它在反应中起作用。

文章建议:

firebase.auth().onAuthStateChanged( user =>; {
  if (user) { this.userId = user.uid }
});

因此,在我的听众中,我尝试将 if 放在 authUser 前面 - 但这似乎不是一种有效的方法。

关于接下来要尝试什么来制作一个让firebase在运行检查之前加载用户的监听器有什么建议吗?

标签: reactjsfirebasegoogle-cloud-firestorefirebase-authentication

解决方案


试试react-with-firebase-auth这个库。
这个库为您提供了一个 withFirebaseAuth() 函数。

import * as React from 'react';
import * as firebase from 'firebase/app';
import 'firebase/auth';

import withFirebaseAuth, { WrappedComponentProps } from 'react-with-firebase-auth';

import firebaseConfig from './firebaseConfig';

const firebaseApp = firebase.initializeApp(firebaseConfig);

const App = ({
  /** These props are provided by withFirebaseAuth HOC */
  signInWithEmailAndPassword,
  createUserWithEmailAndPassword,
  signInWithGoogle,
  signInWithFacebook,
  signInWithGithub,
  signInWithTwitter,
  signInAnonymously,
  signOut,
  setError,
  user,
  error,
  loading,
}: WrappedComponentProps) => (
  <React.Fragment>
    {
      user
        ? <h1>Hello, {user.displayName}</h1>
        : <h1>Log in</h1>
    }

    {
      user
        ? <button onClick={signOut}>Sign out</button>
        : <button onClick={signInWithGoogle}>Sign in with Google</button>
    }

    {
      loading && <h2>Loading..</h2>
    }
  </React.Fragment>
);

const firebaseAppAuth = firebaseApp.auth();

/** See the signature above to find out the available providers */
const providers = {
  googleProvider: new firebase.auth.GoogleAuthProvider(),
};
/** providers can be customised as per the Firebase documentation on auth providers **/
providers.googleProvider.setCustomParameters({hd:"mycompany.com"});

/** Wrap it */
export default withFirebaseAuth({
  providers,
  firebaseAppAuth,
})(App);

推荐阅读