Next.js中使用useEffect获取Firebase数据报Invalid hook call错误如何修复
错误修复方案
你触发的Error: Invalid hook call. Hooks can only be called inside of the body of a function component错误,核心原因是违反了React Hook的调用规则:所有Hook必须在React函数组件的最顶层作用域调用,禁止在嵌套函数、循环、条件判断、useEffect回调内部调用。
你的代码问题出在第二个useEffect内部的map循环里调用了useCollection这个Hook,不符合调用规范。
修复方案
方案1:替换嵌套的useCollection为Firebase原生查询
不需要在循环内使用Hook,直接用Firebase SDK的get()方法异步拉取数据,修改后代码如下:
// 顶层Hook保留,符合调用规范 useEffect(()=>{ console.log("session",session) },[session]); const [myChats] = useCollection(db.collection('chats').where('users','array-contains',session.user.email)); useEffect(()=>{ // 先清空旧数据,避免重复追加 setChats([]) setMyChat([]) // 遍历执行副作用用forEach语义更清晰 myChats?.docs?.forEach(async (user) => { const chatId = user.id setMyChat((prevState) => [...prevState, chatId]) // 直接用原生get方法查询,不需要Hook const chatSnapshot = await db .collection('chats') .doc(chatId) .collection('messeges') .orderBy('timestamp','asc') .limitToLast(1) .get() // 处理查询结果 if(!chatSnapshot.empty) { const chat = chatSnapshot.docs[0] console.log("chat",chat.id) setChats((prev) => [...prev, chat]) } }) },[myChats]) console.log("myChat",chats)
方案2:拆分独立子组件使用useCollection
如果你需要用到useCollection的实时响应更新能力,可以把单条聊天的消息获取逻辑拆为独立子组件,在子组件顶层调用Hook:
- 定义子组件
function ChatItem({ chatId, onChatLoad }) { // 子组件顶层调用Hook,符合规范 const [chatSnapshot] = useCollection( db.collection('chats').doc(chatId).collection('messeges').orderBy('timestamp','asc').limitToLast(1) ) useEffect(() => { if(chatSnapshot?.docs[0]) { const chat = chatSnapshot.docs[0] console.log("chat", chat.id) onChatLoad(chat) } }, [chatSnapshot, onChatLoad]) return <div>{/* 可直接渲染单条聊天内容 */}</div> }
- 父组件逻辑调整
useEffect(()=>{ console.log("session",session) },[session]); const [myChats] = useCollection(db.collection('chats').where('users','array-contains',session.user.email)); useEffect(()=>{ if(myChats?.docs) { setMyChat(myChats.docs.map(user => user.id)) } },[myChats]) // 渲染时遍历生成子组件即可 // return <div>{myChat.map(id => <ChatItem key={id} chatId={id} onChatLoad={(chat) => setChats(prev => [...prev, chat])} />)}</div>
额外注意事项
- 你的代码里消息集合拼写为
messeges,确认是否是手误,正确拼写应为messages,拼写错误会导致查询不到数据 - 每次
myChats更新时先清空旧的聊天列表,避免重复渲染重复数据
内容的提问来源于stack exchange,提问作者Jeevan
相关产品推荐
相关产品推荐

