Javascript 使用react和react firebase挂钩时的无限循环

Javascript 使用react和react firebase挂钩时的无限循环,javascript,reactjs,firebase,google-cloud-firestore,react-hooks,Javascript,Reactjs,Firebase,Google Cloud Firestore,React Hooks,我正在使用一个导航栏,它应该能够使用react和react firebase挂钩在多个聊天室之间切换。() 然而,当我在导航栏中选择一个房间时,聊天室将无限地重新呈现自己 我最初认为这是一个路由器问题,但由于每个房间共享同一个url,问题仍然存在 现在,当我使用导航栏选择房间时,它会使用回调函数将房间号发送回App.js。App.js将把房间号传递给ChatRoom.js,ChatRoom.js将从firestore获取数据,并重新呈现自己 我挣扎了好几天,试图找到任何可能导致无限循环的东西,但

我正在使用一个导航栏,它应该能够使用react和react firebase挂钩在多个聊天室之间切换。()

然而,当我在导航栏中选择一个房间时,聊天室将无限地重新呈现自己

我最初认为这是一个路由器问题,但由于每个房间共享同一个url,问题仍然存在

现在,当我使用导航栏选择房间时,它会使用回调函数将房间号发送回App.js。App.js将把房间号传递给ChatRoom.js,ChatRoom.js将从firestore获取数据,并重新呈现自己

我挣扎了好几天,试图找到任何可能导致无限循环的东西,但收效甚微。任何帮助都将不胜感激

聊天室

import React,{usemo,useRef,useState}来自“React”;
从“react router”导入{withRouter};
从'react firebase hooks/firestore'导入{useCollectionData,useDocument,useDocumentData};
从“../firebase.js”导入firebase,{firestore,auth};
从“/ChatMessage”导入ChatMessage;
const聊天室2=(道具)=>{
console.log(“聊天室渲染”);
函数saveQuery(){
const channelid=props.channelid;
const messagesRef=firestore.collection('messages').doc(channelid.collection('chats');
const query=messagesRef.orderBy('createdAt').limitToLast(25);
返回[messagesRef,query];
}
var returnedVal=useMoom(()=>saveQuery[props.channelid]);
const messagesRef=returnedVal[0];
const query=returnedVal[1];
const[messages]=useCollectionData(查询,{idField:'id'});
常量[formValue,setFormValue]=useState(“”);
const sendMessage=async(e)=>{
e、 预防默认值();
console.log(messagesRef);
console.log(查询);
控制台日志(消息);
const{uid,photoURL}=auth.currentUser;
等待消息ref.add({
text:formValue,
createdAt:firebase.firestore.FieldValue.serverTimestamp(),
uid,
照片网址
})
setFormValue(“”);
}
返回(
{messages&&messages.map(msg=>)}
setFormValue(e.target.value)}占位符=“说点好话”/>
问题摘要
useCollectionData
query
参数上进行记忆,但由于每个渲染周期都声明了一个新的
query
引用,因此firebase钩子将重新运行并更新集合,并重新渲染组件

const { channelid } = props;
const messagesRef = firestore
  .collection('messages')
  .doc(channelid)
  .collection('chats');
const query = messagesRef // <-- new query reference
  .orderBy('createdAt')
  .limitToLast(25);

const [messages] = useCollectionData(
  query, // <-- reference update trigger hook
  { idField: 'id' },
);

你能分辨出哪个组件是渲染循环吗?你有没有进一步简化你的代码来隔离哪个组件/钩子使用触发了渲染循环?嗨,谢谢你的回答。聊天室组件导致了无限循环,发生的事件顺序是:应用程序渲染->聊天室列表渲染->聊天室渲染->聊天室列表刷新nders->chat room呈现无限。在chunk.js文件中,它说“const{channelid}=props.channelid;”是导致错误的原因。我是react新手,如果我说的某些事情没有任何意义,我很抱歉。可能很难用这些代码创建一个运行的codesandbox(您可以尝试)。几点想法。(1)如果您在聊天室组件中使用了
useCollectionDataOnce
hook会怎么样?(2)如果您注释掉
const[messages]=useCollectionData(查询,{idField:'id})
在聊天室中是否仍然呈现循环?能否包含一个更完整的
app.js
组件,以便我们可以看到如何维护回调和
roomNum
值。您好,感谢您再次回复!我尝试了您的建议。1)在聊天室中使用useCollectionDataOnce挂钩也会导致无限循环。2) 删除useCollectionData不会导致无限循环。3) 我更新了App.js,它现在包含回调函数和roomNum state。谢谢。好的,我怀疑这可能是由于
query
在每个渲染周期被重新声明,而
query
最终成为
useCollectionData
钩子依赖项(我已经翻遍了源代码,我想就是这样)。尝试使用
usemo
钩子来记忆
query
值,该值依赖于
channelid
属性,因此
query
useCollectionData
钩子的稳定参考值。
const { channelid } = props;

const query = useMemo(() => {
  const messagesRef = firestore
    .collection('messages')
    .doc(channelid)
    .collection('chats');
  const query = messagesRef.orderBy('createdAt').limitToLast(25);
  return query;
}, [channelid]);

const [messages] = useCollectionData(
  query,  // <-- stable reference
  { idField: 'id' },
);