React中Google OAuth登录后无法跳转至首页问题排查
问题描述
我在React中参照YouTube教程搭建Google OAuth登录页面,登录流程看似正常,但完成登录后无法跳转至首页。未添加空校验时,出现以下错误:
Cannot destructure property 'name' of 'response.profileObj'
添加空校验后错误消失,但跳转首页的功能仍未实现,Login.jsx代码如下:
import React from 'react' import GoogleLogin from 'react-google-login'; import { useNavigate } from 'react-router-dom'; import { FcGoogle } from 'react-icons/fc'; import carVideo from '../assets/car.mp4'; import logo from '../assets/speedograph white.png'; import { client } from '../client'; const Login = () => { const navigate = useNavigate(); const responseGoogle = (response) => { localStorage.setItem('user', JSON.stringify(response.profileObj)); if (response.profileObj) { const { name, googleId, imageUrl } = response.profileObj; const doc = { _id: googleId, _type: 'user', userName: name, image: imageUrl, }; client.createIfNotExists(doc).then(() => { navigate('/', { replace: true }); }); } }; return ( <div className = "flex justify-start items-center flex-col h-screen"> <div className='relative w-full h-full'> <video src={carVideo} type='video/mp4' loop controls={false} muted autoPlay className='w-full h-full object-cover' /> <div className = "absolute flex flex-col justify-center items-center top-0 right-0 left-0 bottom-0 bg-blackOverlay"> <div className="p-5 ml-3"> <img src={logo} width="130px" alt="logo" /> </div> <div className='shadow-2xl'> <GoogleLogin clientId={process.env.REACT_APP_GOOGLE_API_TOKEN} render={(renderProps) => ( <button type='button' className='bg-white flex justify-center items-center p-3 rounded-lg cursor-pointer outline-none' onClick={renderProps.onClick} disabled={renderProps.disabled} > <FcGoogle className='mr-4' />Sign in with Google </button> )} onSuccess={responseGoogle} onFailure={responseGoogle} cookiePolicy="single_host_origin" /> </div> </div> </div> </div> ) } export default Login
问题排查与修复方案
1. 合并成功/失败回调导致逻辑混乱
你将onSuccess和onFailure都绑定到了同一个responseGoogle函数,当用户取消登录(失败场景)时,response.profileObj为undefined,空校验会跳过跳转逻辑;而如果登录成功后client.createIfNotExists执行出错,也会导致跳转不触发。
修复:拆分成功与失败回调
// 新增失败处理函数 const handleLoginFailure = (response) => { console.error('登录失败:', response); // 可在此添加用户提示,比如弹窗告知登录失败 }; // 修改GoogleLogin组件的回调绑定 <GoogleLogin clientId={process.env.REACT_APP_GOOGLE_API_TOKEN} render={(renderProps) => ( <button type='button' className='bg-white flex justify-center items-center p-3 rounded-lg cursor-pointer outline-none' onClick={renderProps.onClick} disabled={renderProps.disabled} > <FcGoogle className='mr-4' />Sign in with Google </button> )} onSuccess={responseGoogle} onFailure={handleLoginFailure} // 替换为单独的失败处理函数 cookiePolicy="single_host_origin" />
2. 未处理数据保存的异常
client.createIfNotExists执行时可能因网络问题、Sanity配置错误等抛出异常,此时then块不会执行,跳转逻辑也就无法触发。
修复:添加异常捕获
client.createIfNotExists(doc) .then(() => { navigate('/', { replace: true }); }) .catch(err => { console.error('保存用户数据失败:', err); // 可选:提示用户保存失败,但仍跳转首页 navigate('/', { replace: true }); });
3. 提前存入无效数据到localStorage
你在空校验之前就执行了localStorage.setItem('user', JSON.stringify(response.profileObj)),如果登录失败,response.profileObj是undefined,会把字符串"undefined"存入localStorage,可能影响后续页面的登录状态判断。
修复:将localStorage存储移到空校验内部
const responseGoogle = (response) => { if (response.profileObj) { // 仅当存在用户信息时才存入localStorage localStorage.setItem('user', JSON.stringify(response.profileObj)); const { name, googleId, imageUrl } = response.profileObj; const doc = { _id: googleId, _type: 'user', userName: name, image: imageUrl, }; client.createIfNotExists(doc) .then(() => { navigate('/', { replace: true }); }) .catch(err => { console.error('保存用户数据失败:', err); navigate('/', { replace: true }); }); } else { console.error('登录响应中无有效用户信息:', response); } };
4. 检查路由配置
确保你的路由配置中,/路径对应的首页组件已正确注册,且没有被未正确配置的登录拦截逻辑阻止(比如拦截逻辑读取localStorage时存在时序问题)。
内容的提问来源于stack exchange,提问作者Segmentation Fraud

