React+Sanity项目Google登录用户头像获取undefined问题排查
问题排查与修复方案
你遇到的头像显示undefined、用户数据获取失败的问题,主要是localStorage处理逻辑错误、useEffect依赖缺失、字段名不匹配、查询参数错误这几个原因导致的,下面逐个修复:
1. 修复localStorage判断逻辑
原代码的判断逻辑存在错误:当localStorage中没有user项时,getItem返回的是null而非字符串'undefined',会错误执行localStorage.clear()(且该方法无返回值,导致userInfo为undefined)。
修复后代码:
const Home = () => { const [toggleSidebar, setToggleSidebar] = useState(false); const [user, setUser] = useState(null); // 优化localStorage读取逻辑 const storedUser = localStorage.getItem('user'); const userInfo = storedUser ? JSON.parse(storedUser) : null; // 无用户数据时清除本地存储(可选) if (!userInfo) localStorage.clear(); // ...后续代码 }
2. 修复useEffect依赖与查询参数
原useEffect依赖数组为空,且传入userQuery的参数错误:你在Login组件中将Sanity用户文档的_id设为Google返回的userObject.sub,但Home组件传的是userInfo?.googleId,导致查询不到数据;同时依赖缺失会导致userInfo变化时无法重新触发查询。
修复后代码:
useEffect(() => { // 无用户数据时直接返回 if (!userInfo) return; // 传入正确的用户标识:userInfo.sub const query = userQuery(userInfo.sub); client.fetch(query) .then((data) => { setUser(data[0]); }) .catch(err => console.error('获取用户数据失败:', err)); // 新增错误捕获,方便排查 }, [userInfo]); // 加入userInfo作为依赖,数据变化时重新查询
3. 修复头像字段名不匹配
Login组件中存储到Sanity的头像字段是image,但Home组件渲染时用的是user?.picture,字段名不匹配导致取不到值。
修复后代码:
<Link to={`user-profile/${user?._id}`}> {/* 将user?.picture改为user?.image,匹配Sanity存储的字段名 */} <img src={user?.image} alt="用户头像" className='w-28'/> </Link>
4. 额外优化:添加异步加载状态
因为从Sanity获取数据是异步操作,初始时user为null,可以添加加载状态避免显示异常:
const Home = () => { const [toggleSidebar, setToggleSidebar] = useState(false); const [user, setUser] = useState(null); const [loading, setLoading] = useState(true); // 新增加载状态 const storedUser = localStorage.getItem('user'); const userInfo = storedUser ? JSON.parse(storedUser) : null; if (!userInfo) localStorage.clear(); useEffect(() => { if (!userInfo) { setLoading(false); return; } const query = userQuery(userInfo.sub); client.fetch(query) .then((data) => { setUser(data[0]); setLoading(false); }) .catch(err => { console.error('获取用户数据失败:', err); setLoading(false); }); }, [userInfo]); return ( <div className='flex bg-gray-50 md:flex-row flex-col h-screen transaction-height duration-75 ease-out'> {/* ...其他代码 */} <div className='flex md:hidden flex-row'> <HiMenu fontSize={40} className="cursor-pointer" onClick={() => setToggleSidebar(false)} /> <Link to="/"> <img src={logo} alt="logo" className="w-28" /> </Link> {/* 根据加载状态渲染不同内容 */} {loading ? ( <div className='w-28 h-28 bg-gray-200 rounded-full'></div> ) : user ? ( <Link to={`user-profile/${user._id}`}> <img src={user.image} alt="用户头像" className='w-28'/> </Link> ) : ( <div className='text-sm'>未登录</div> )} </div> </div> ) }
内容的提问来源于stack exchange,提问作者Segmentation Fraud
相关产品推荐
相关产品推荐

