Ionic/React自定义Hook获取Firebase数据触发no-unused-expressions报错
报错原因
@typescript-eslint/no-unused-expressions 报错的直接原因是useEffect内的异步立即执行函数(IIFE)写法错误:你只声明了匿名异步函数,没有在函数定义末尾加()触发执行,ESLint会将这段未被调用、也未产生赋值效果的函数定义判定为无效表达式,因此抛出规则校验错误。
原代码中IIFE的错误写法:
// 仅定义了函数,没有执行 (async () => { const doc = await db.collection("Users").doc(userid).get(); setuserDetails(({...doc.data(), id: doc.id})) }) // 这里少了末尾的(),函数根本不会运行
除了直接触发报错的写法问题,代码还存在几个会导致运行异常的隐患:
- 未做登录态校验:用户未登录时
getAuth().currentUser为null,userid会取到undefined,直接发起Firestore查询会抛出请求错误 - useEffect依赖数组缺失
userid:当用户登录态变化、uid更新时,不会自动重新拉取最新的用户数据 - state类型与初始值不匹配:用户详情为对象结构,初始值传入空数组、类型标注为unknown不符合实际使用场景
- 缺少组件卸载拦截:如果请求返回前组件已经卸载,调用
setuserDetails会触发React内存泄漏警告
修复方案
- 修正异步函数的执行逻辑,避免无效表达式报错
- 增加userid空值判断,未登录时跳过无效请求
- 将userid加入useEffect依赖数组,保证登录态变化时数据同步
- 修正state的类型定义与初始值,增加错误捕获和卸载拦截,避免运行时异常
修复后的完整可运行代码:
import { useEffect, useState } from 'react'; import { firestore } from '../../' import { getAuth } from 'firebase/auth'; // 可根据业务实际的用户字段替换类型定义 type UserInfo = { id?: string; username?: string; avatar?: string; [key: string]: unknown; } export function useUserDetails() { const db = firestore; const userId = getAuth().currentUser?.uid; // 初始值设为null,类型匹配用户对象结构 const [userDetails, setUserDetails] = useState<UserInfo | null>(null); useEffect(() => { // 未登录直接返回,不发起请求 if (!userId) return; let isMounted = true; const fetchUserData = async () => { try { const docSnap = await db.collection("Users").doc(userId).get(); // 组件未卸载、文档存在时才更新状态 if (isMounted && docSnap.exists()) { setUserDetails({ ...docSnap.data(), id: docSnap.id }); } } catch (error) { console.error('获取用户数据失败:', error); } }; fetchUserData(); // 组件卸载时更新标记,避免内存泄漏 return () => { isMounted = false; }; }, [userId]); // 以对象形式返回,使用时不需要关心数组顺序 return { userDetails }; }
额外说明
如果要保留IIFE写法,只需要给原代码的IIFE补上末尾的执行括号即可解决ESLint报错,但依然建议同步修复上面提到的其他隐患,避免线上运行异常。正确的IIFE写法示例:
useEffect(() => { (async () => { // 异步逻辑 })(); // 末尾必须加()触发执行 }, [])
内容的提问来源于stack exchange,提问作者user6358067
相关产品推荐
相关产品推荐

