rakannimer / react-firebase

🔥Declarative React bindings for Firebase Auth & Realtime Database.
https://react-firebase-js.com/
228 stars 32 forks source link

How to know if data is loading to display loading screen rather than login page? #39

Open Ahmdrza opened 4 years ago

Ahmdrza commented 4 years ago

I need to display loading screen rather than displaying login screen while data is being fetched. Can you please tell me about it? I have checked docs but I didn't find anything. Thanks.

nk2580 commented 4 years ago

the issue here appears to be the authState doesn't have a loading value. its probably no that difficult to add one in. did you want to work on a PR?

Ahmdrza commented 4 years ago

Yes I can work on it. But I don't get much free time so i'll be a slow a bit.

rohan-deshpande commented 3 years ago

Just hit this issue and it's... not ideal. Seems like there is a semi official Google maintained React bindings lib here https://github.com/FirebaseExtended/reactfire which supports loading states but the docs are SO Google. Seems unfinished and hard to follow.

For now one way around it is to store the current user in local storage and simply redirect away from the login page if they exist there. Not the best solution, but better than rendering confusing UI in my opinion until this is resolved.

Edit: seems like @rakannimer is using https://github.com/csfrequency/react-firebase-hooks in his NextJs demo app which has a loading state provided through the useAuthState hook so it might be good to check that out as well

rohan-deshpande commented 3 years ago

As a possible solution I created my own AuthProvider component which passes loading to children via render props

import { Component } from 'react';
import firebase from 'firebase/app';
import { func } from 'prop-types';

export class AuthProvider extends Component {
  state = {
    loading: firebase.auth().currentUser === null,
    user: firebase.auth().currentUser,
  };

  componentDidMount() {
    firebase
      .auth()
      .onAuthStateChanged(
        user => user && this.setState({ user, loading: false })
      );
  }

  render() {
    const { loading, user } = this.state;

    return this.props.children({ loading, user });
  }
}

AuthProvider.propTypes = {
  children: func,
};

That being said, I've migrated to using react-firebase-hooks as it seems to be a little more active

rohan-deshpande commented 3 years ago

Just found this and it lines up with my own observations - it's impossible to know if the user is logged in instantly without using local storage https://stackoverflow.com/a/51856627/12128359. The firebase.auth().currentUser method is not instant, I guess it makes some sort of async call.

Probably an okay solution would be to wire in ways to store the user in local storage within a provider like this. That way you can easily mutate the value in local storage in the onAuthStateChanged observer callback and have it be accurate.