如何默认用户状态以登录用户Firebase和React

时间:2018-08-04 19:04:58

标签: javascript reactjs firebase firebase-authentication

我刚刚使用React和Firebase在我的Web应用程序中实现了身份验证。效果很好,但我意识到,对于每次页面更改或刷新,它首先会将状态默认为空用户。 AuthChangeListener立即触发并检测到已登录内容并重新渲染屏幕。我知道这是React的工作方式,但是如何将当前用户状态默认为当前登录的用户。到目前为止,它看起来像是快速闪烁。

export default class Router extends Component {

  constructor(props)
  {
    super(props);
    this.state = {
      user:null
    }
    this.login = this.login.bind(this);
    this.logout = this.logout.bind(this);
  }
  authListener()
  {
    // fetch current user
    auth.onAuthStateChanged((user) => {
      if (user) {
        this.setState({
          user:user
        });
      }
      else {
        this.setState({
          user:null
        });
      }
   });
  }
  componentDidMount()
  {
    this.authListener();
  }

render()
  {
    return(
      <BrowserRouter>
        <Switch>
          <Route exact path="/donate" component = {() => <Donate user={this.state.user} />}/>
          <Route exact path="/" component = {() => <Donate user={this.state.user} />}/>
          <Route exact path="/news" component = {News}/>
          <Route exact path="/about" component = {About}/>
          <Route exact path="/auth" component = {() => <Auth user={this.state.user} login={this.login} logout={this.logout}/>}/>
          <Route exact path="/funded" component = {Funded}/>
          <Route exact path="/contact" component = {Contact}/>
          <Route path="*" component={Error} />
        </Switch>
      </BrowserRouter>
    )
  }
}

1 个答案:

答案 0 :(得分:0)

我记得碰到过这样的事情。不幸的是,onAuthStateChanged在会话状态更改(用户登录/注销)时起作用,但是它不会告诉您是否有活动的会话。

我发现处理此问题的唯一方法是使用重复计时器检查currentUser属性,并将state属性设置为false,直到结果返回null或当前会话为止,尝试次数。计时器运行时,我在屏幕上有一个叠加层和一个旋转计时器,让用户知道该应用程序正在运行。如果结果为null(无用户会话),则显示登录表单。如果活动会话又回来了,请显示相应的组件。

constructor(){
  super();
  this.state = { sessionChecks: 0 };
  this.auth = firebase.auth();
  this.checkActiveUser = this.checkActiveUser.bind(this);
}

checkActiveUser(){
  const loggedUser = this.auth.currentUser;
  // set this to the amount of tries you want
  if( !loggedUser && this.state.sessionChecks < 3) {
    setTimeout( () => {
      // no user session, check again
      this.setState({ sessionChecks: ( sessionChecks + 1 ) });
      this.checkActiveUser();
    }, 500); // change the time to what you want
  } else if(loggedUser) {
    // there is an active user, run your code here
  }
}

仍然需要使用计时器检查用户会话的另一个选项是使用reload的{​​{1}}方法,该方法返回一个可以在异步代码中使用的承诺:

https://firebase.google.com/docs/reference/js/firebase.User?authuser=0#reload


编辑

为了立即检查用户会话,我想到的解决方案是创建一个包含所有路由的组件,并将该组件添加到主应用程序文件中。

这是主应用程序文件(index.js)

currentUser

const App = => <Provider store={appStore}> <Router> <Routes /> </Router> </Provider>; 被传递给ReactDOM的render方法。路由器是通过以下方式导入的BrowserRouter:App。路由是所有路由的组成部分。该组件在应用程序的生命周期中仅安装了一次。

这里是import { BrowserRouter as Router } from "react-router-dom";组件(至少是其中的相关部分):

<Routes />

现在,在检查代码的同时,您不仅可以一直显示登录组件,还可以在登录组件上显示带有微调器和消息的覆盖图,并且当检查完成时,可以独立显示是否有活动的会话或否,请隐藏该覆盖并显示渲染的组件,无论是登录组件还是用于特定路线的组件。

希望这会有所帮助。