Javascript 了解何时何地需要使用onAuthStateChanged()-Firebase/Next.js

Javascript 了解何时何地需要使用onAuthStateChanged()-Firebase/Next.js,javascript,google-cloud-firestore,firebase-authentication,next.js,Javascript,Google Cloud Firestore,Firebase Authentication,Next.js,这是从示例(Next.js)构建的项目的index.js页面 const Index=()=>{ const{user,logout}=useUser(); 如果(!用户){ 返回( 试验 您尚未登录。{“”} 登录 ); } 返回( ); }; 出口违约指数; 客户端组件用于列出一组firestore文档。以下是组件的编写方式: const Clients = () => { const { user, logout } = useUser(); const [cl

这是从示例(Next.js)构建的项目的index.js页面

const Index=()=>{
const{user,logout}=useUser();
如果(!用户){
返回(
试验

您尚未登录。{“”} 登录

); } 返回( ); }; 出口违约指数;
客户端组件用于列出一组firestore文档。以下是组件的编写方式:

const Clients = () => {
    const { user, logout } = useUser();
    const [clients, setClients] = useState([]);
    var userRef = firebase.auth().currentUser;
    
    useEffect(() => {
    firebase.firestore()
      .collection('users')
      .doc(userRef.uid)
      .collection('clients')
      .onSnapshot(snap => {
        const clients = snap.docs.map(doc => ({
          id: doc.id,
          ...doc.data()
        }));
        setClients(clients);
      });
  }, []);
  
    return (
        <div>
        <ul>
          {clients.map(client =>
            <li key={client.id}>
              {client.name}
            </li>
          )}
        </ul>
      </div>
    );
  };
  
  export default Clients;
const客户端=()=>{
const{user,logout}=useUser();
const[clients,setClients]=useState([]);
var userRef=firebase.auth().currentUser;
useffect(()=>{
firebase.firestore()
.collection('用户')
.doc(userRef.uid)
.collection(“客户”)
.onSnapshot(快照=>{
const clients=snap.docs.map(doc=>({
id:doc.id,
…文件数据()
}));
客户(客户);
});
}, []);
返回(
    {clients.map(client=>
  • {client.name}
  • )}
); }; 导出默认客户端;
如果在index.js中,返回是以存在用户对象为条件的,那么在该返回中的客户端如何可以将“user”视为未定义

我尝试使用onAuthStateChanged()并尝试使用firebase.auth().currentUser来代替用户引用和user.uid-我不断遇到以下错误:

无法读取未定义的属性“uid”

未定义用户

客户端(…)返回空

我想我的问题的答案是“确保在尝试访问user.uid之前等待firebase auth”-但我似乎无法在客户端实现这一点

更新 当尝试使用onAuthStateChanged在尝试与其uid交互之前验证用户是否存在时,我遇到了一个错误“渲染的钩子比上次渲染时多”

分别地

实际上,我通过删除useEffect并将其写成这样,获得了(某种程度上)想要的效果:

const Clients = () => {


    firebase.auth().onAuthStateChanged(function(user) {
        if (user) {

          const db = firebase.firestore();
          db.collection('users')
          .doc(user.uid)
          .collection('clients')
          .onSnapshot(snap => {
              const clients = snap.docs.map(doc => ({
                  id: doc.id,
                  ...doc.data()
              }));
              setClients(clients);
          });
        } else {
         []
        }
      });

    const [clients, setClients] = useState([]);
   
    return (
        <div>
        <ul>
          {clients.map(client =>
            <li key={client.id}>
              {client.name}
            </li>
          )}
        </ul>
      </div>
    );
  };
  
  export default Clients;
const客户端=()=>{
firebase.auth().onAuthStateChanged(函数(用户){
如果(用户){
const db=firebase.firestore();
db.collection('用户')
.doc(user.uid)
.collection(“客户”)
.onSnapshot(快照=>{
const clients=snap.docs.map(doc=>({
id:doc.id,
…文件数据()
}));
客户(客户);
});
}否则{
[]
}
});
const[clients,setClients]=useState([]);
返回(
    {clients.map(client=>
  • {client.name}
  • )}
); }; 导出默认客户端;
然而,这显然不像我注销时那样“正确”——我在控制台中收到大约30000条错误消息,上面说:

快照侦听器中的react_devtools_backend.js:2273未捕获错误: FirebaseError:缺少或权限不足


但是,当我以任何用户身份登录时,我会得到正确呈现的列表,而不会出现控制台错误。

用户/客户端集合是否不断变化?或者为什么要使用onSnapshot?是的,客户列表将定期(不一定经常)更改-客户最终也将有一个文档“记录”集合,这些文档将更新得更加频繁。在完成以下操作后,我将使用onSnapshot:
const Clients = () => {


    firebase.auth().onAuthStateChanged(function(user) {
        if (user) {

          const db = firebase.firestore();
          db.collection('users')
          .doc(user.uid)
          .collection('clients')
          .onSnapshot(snap => {
              const clients = snap.docs.map(doc => ({
                  id: doc.id,
                  ...doc.data()
              }));
              setClients(clients);
          });
        } else {
         []
        }
      });

    const [clients, setClients] = useState([]);
   
    return (
        <div>
        <ul>
          {clients.map(client =>
            <li key={client.id}>
              {client.name}
            </li>
          )}
        </ul>
      </div>
    );
  };
  
  export default Clients;