【问题标题】:onAuthStateChanged doesn't seem to work with React context apionAuthStateChanged 似乎不适用于 React 上下文 API
【发布时间】:2019-02-02 11:59:17
【问题描述】:

我目前正在关注 Robin Wieruch 所著的“与 Firebase 反应之路”一书。我遇到的问题是,当我刷新使用 Context API 的页面时,来自 Firebase 的 authUser 变为 null。

这是我的 app.js

import Navigation from './Navigation';
import LandingPage from './Landing';
import AccountPage from './Account';
import withAuthentication from './withAuthentication';

import * as routes from '../constants/routes';

const App = () =>
        <Router>
        <div>
        <h3 className="alt-h3" style={{textAlign: "center"}}>Soundyladder</h3>

          <Navigation />
          <hr/>

          <Route
            exact path={routes.LANDING}
            component={LandingPage}
          />


              <Route
            exact path={routes.ACCOUNT}
            component={AccountPage}
          />
        </div>
      </Router>

export default withAuthentication(App);

如您所见,app.js 使用的是高阶组件。

withAuthentication.js:

import AuthUserContext from './AuthUserContext';

const withAuthentication = (Component) => {
    class withAutnetication extends React.Component {
        constructor(props) {
            super(props);

            this.state = {
                authUser: null
            };
        }

        componentDidMount() {

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

            });

        }

        render() {
            const { authUser } = this.state;
            console.log(this.state);
            return (

                <AuthUserContext.Provider value={authUser}>
                    <Component { ...this.props } />
                </AuthUserContext.Provider>
            )
        }
    }

    return withAutnetication;
}

export default withAuthentication;

正如您在此处看到的,我提供了 Context API,以便 App.js 下的每个组件都可以使用它。

这里是 AuthUserContext:

import React from 'react';

const AuthUserContext = React.createContext(null);

export default AuthUserContext;

问题是当我访问账户页面,然后刷新页面时,authUser变成了null。

Account.js:

const AccountPage = () =>
    <AuthUserContext.Consumer>
        {authUser =>

            <div>
                <h1>Account: {authUser.email}</h1>
                <PasswordForgetForm />
                <PasswordChangeForm />
            </div>
        }
    </AuthUserContext.Consumer>

    export default AccountPage;

但是,当我在 LandingPage 并刷新页面时,authUser 不会变为 null。

这是我的登陆页面:

const LandingPage = () =>
    <div>
        <h1>Landing Page</h1>
    </div>

export default LandingPage;

但是,如果我尝试在登录页面中使用 Context API 中的 authUser,就像我在帐户页面中所做的那样,我会收到相同的错误:authUser 变为 null。

Context API 好像有问题?

【问题讨论】:

    标签: javascript reactjs firebase firebase-authentication


    【解决方案1】:

    我不确定“与 Firebase 做出反应的道路”一书中的身份验证策略是什么,但您遇到的问题可以这样简单地解释。

    帐户页面重新加载

    在第一次渲染时(在您刷新页面之后),React 首先挂载所有可用的内容。然后它会在您的withAuthentication HOC 中触发componentDidMount 方法。

    这意味着,在第一次渲染时(在您刷新页面之后)上下文值authUser 是null。

    React 抛出一个错误(这就是正在发生的事情吗?)然后停止执行。因此永远不会在 HOC 中联系到您的 componentDidMount。

    Cannot read property 'email' of null
    

    着陆页重新加载

    在这里,React 不会停止执行,因为它可以渲染所有内容。然后在 HOC 中触发 componentDidMount,firebase 获取用户(异步)。当您导航到“帐户页面”时,用户已被加载,因此您的 authUser 不再是 null。

    潜在的简单修复

    同样,不确定这本书提供了什么样的 Auth 策略,但要解决这个问题,你可以在你的 HOC 中简单地按照这些思路做一些事情

    render() {
      const { authUser } = this.state;
    
      if (!authUser) {
        return null;
      }
    
      return (
        <AuthUserContext.Provider value={authUser}>
          <Component { ...this.props } />
        </AuthUserContext.Provider>
      )
    }
    

    或者您可以在您的“帐户页面”中添加支票

    <h1>Account: {authUser ? authUser.email : null}</h1>
    

    可以在in this codesandbox 找到一个非常粗略的示例。我使用 setInterval 而不是 firebase auth 方法。让我知道它会有所帮助并清除问题。

    【讨论】:

      猜你喜欢
      • 2017-12-13
      • 1970-01-01
      • 1970-01-01
      • 2020-04-04
      • 2022-10-05
      • 1970-01-01
      • 1970-01-01
      • 2020-04-04
      • 2023-04-06
      相关资源
      最近更新 更多