React useEffect中访问currentUser.uid提示未定义如何解决
报错原因
useAuth自定义Hook中currentUser的初始值是undefined,Firebase的onAuthStateChanged鉴权监听是异步执行的,组件首次渲染时鉴权结果还没返回,此时拿到的currentUser就是初始的undefined。Chat组件里的useEffect传入了空依赖数组,只会在组件首次挂载时执行一次,执行时闭包捕获的就是首次渲染阶段的undefined值。后续鉴权完成currentUser更新为真实用户对象时,这个effect不会重新触发,自然拿不到最新的用户值,访问uid属性就会触发未定义报错。
修复方案
核心是给effect加上正确的依赖,同时增加空值判断,等用户信息加载完成后再执行业务逻辑:
function Chat() { const currentUser = useAuth() useEffect(() => { // 用户信息未加载完成时直接终止逻辑 if (!currentUser) return const fetchParticipants = async () => { console.log(currentUser.uid) // 此时currentUser一定存在 // 后续拉取参会人相关逻辑 } fetchParticipants() }, [currentUser]) // 将currentUser加入依赖数组,用户状态更新时重新执行effect }
如果需要区分「鉴权加载中」「未登录」「已登录」三种状态,避免逻辑混淆,可以优化useAuth的状态定义:
export function useAuth() { // 初始值null代表鉴权状态加载中,false代表未登录,对象值代表已登录用户 const [currentUser, setCurrentUser] = useState(null); useEffect(() => { const unsub = onAuthStateChanged(auth, user => setCurrentUser(user ?? false)); return unsub; }, []) return currentUser; }
对应组件内的逻辑可以写得更严谨:
function Chat() { const currentUser = useAuth() useEffect(() => { // 鉴权状态未加载完成,等待 if (currentUser === null) return // 鉴权完成但用户未登录,可做跳转登录页、提示等处理 if (currentUser === false) { console.log('用户未登录') return } const fetchParticipants = async () => { console.log(currentUser.uid) // 业务逻辑 } fetchParticipants() }, [currentUser]) }
注意:不要为了绕过依赖检查使用ref存储currentUser值,这种写法会破坏React的状态响应流,很容易引发其他不同步的隐性bug,按照React官方规则补全依赖、增加状态判断是最稳妥的实现方式。
内容的提问来源于stack exchange,提问作者Cyberguy Game
相关产品推荐
相关产品推荐

