【问题标题】:How to set up firebase auth onAuthStateChanged() listener run when React app is loaded?加载 React 应用程序时如何设置 firebase auth onAuthStateChanged() 监听器运行?
【发布时间】:2019-10-29 00:28:14
【问题描述】:

我正在尝试在我的顶级组件 App 上设置 Firebase 身份验证侦听器,以便通过 React 上下文向所有其他组件提供 authUser 对象。

我目前正在这样做:

function App() {
  console.log('Rendering App...');
  const [authUser,setAuthUser] = useState(null);
  const [authWasListened,setAuthWasListened] = useState(false);

  useEffect(()=>{
    console.log('Running App useEffect...');
    return firebase.auth().onAuthStateChanged(
      (authUser) => {

        console.log(authUser);
        console.log(authUser.uid);

        if(authUser) {
          setAuthUser(authUser);
          setAuthWasListened(true);
        } else {
          setAuthUser(null);
          setAuthWasListened(true);
        }

      }
    );

  },[]);

  return(
    authWasListened ?
    <Layout/>
    : <div>Waiting for auth...</div>
  );

}

但是我得到了日志输出:

Rendering App...
Running App useEffect...

似乎我正在设置侦听器,但它一开始并没有运行,因此它没有获得当前的身份验证状态(它为空,因为我什至还没有登录表单)。它似乎在等待变化发生。

authListener不应该先获取当前authUser的状态,然后再监听变化吗?我做错了什么?

更新

我发现我做错了什么。 useEffect 应该返回一个函数来清除unmount 上的侦听器,而不是函数调用,就像我在上面尝试做的那样。所以我的听众从来没有被设置过。

现在按预期工作:

useEffect(()=>{
    console.log('Running App useEffect...');
    const authListener = firebase.auth().onAuthStateChanged(
      (authUser) => {

        console.log(authUser);
        console.log(authUser.uid);

        if(authUser) {
          setAuthUser(authUser);
          setAuthWasListened(true);
        } else {
          setAuthUser(null);
          setAuthWasListened(true);
        }

      }
    );
    return authListener;  // THIS MUST BE A FUNCTION, AND NOT A FUNCTION CALL

  },[]);

【问题讨论】:

    标签: javascript reactjs firebase firebase-authentication


    【解决方案1】:

    侦听器不是即时的。从页面第一次加载的那一刻起,状态的变化可能需要一些时间。如果您想立即检查用户是否已登录,可以使用currentUser,但同样,更新可能需要一些时间,因此侦听器是更好的选择。

    【讨论】:

    • 谢谢,道格。即使需要一些时间,听众会在某个时候开火吗?即使没有任何新的登录/注销?我的意思是在单页应用程序上下文中。如果我在任何时候刷新页面,我的应用程序将重新呈现。我的代码(当前编写的方式)会检测到身份验证状态吗?还是我需要用var user = firebase.auth().currentUser; 检查当前状态?
    • 是的,当登录用户发生变化时会调用监听器。
    【解决方案2】:

    https://reactjs.org/docs/hooks-effect.html#example-using-hooks-1

    为什么我们从效果中返回一个函数?这是效果的可选清理机制。每个效果都可能返回一个在它之后进行清理的函数。这让我们可以保持添加和删除订阅的逻辑彼此接近。它们是相同效果的一部分!

    React 究竟何时清理效果? React 在组件卸载时执行清理。然而,正如我们之前所了解的,效果会为每次渲染运行,而不仅仅是一次。这就是为什么 React 还会在下次运行效果之前清理上一次渲染中的效果。我们将在下文讨论为什么这有助于避免错误以及如何选择退出这种行为,以防它在后面产生性能问题。

    看看Set an authentication state observer and get user data

    试试下面的代码。

    function App() {
      console.log('Rendering App...');
      const [authUser,setAuthUser] = useState(null);
      const [authWasListened,setAuthWasListened] = useState(false);
    
      useEffect(()=>{
        console.log('Running App useEffect...');
        firebase.auth().onAuthStateChanged(
          (authUser) => {
    
            console.log(authUser);
            console.log(authUser.uid);
    
            if(authUser) {
              setAuthUser(authUser);
              setAuthWasListened(true);
            } else {
              setAuthUser(null);
              setAuthWasListened(true);
            }
    
          }
        );
      },[]);
    
      return(
        authWasListened ?
        <Layout/>
        : <div>Waiting for auth...</div>
      );
    
    }
    

    【讨论】:

      猜你喜欢
      • 2016-09-19
      • 2016-10-28
      • 2016-12-29
      • 2020-09-22
      • 1970-01-01
      • 1970-01-01
      • 2018-02-20
      • 2018-08-11
      • 1970-01-01
      相关资源
      最近更新 更多