express-graphql与react-apollo错误处理:登录错误无法正常展示
排查登录错误提示不显示的问题:服务器端 vs React 客户端
Hey there! Let's walk through how to diagnose why you're not seeing the "邮箱与密码不匹配" error message, and figure out which repo to file your issue in.
第一步:先确认服务器端是否正确返回GraphQL错误
首先咱们得排除服务器端的问题——直接用GraphQL Playground(或者你常用的GraphQL调试工具)调用登录mutation,输入错误的邮箱/密码,看看返回的响应结构。
检查Resolver的错误抛出逻辑
你的服务器端Resolver必须明确抛出GraphQLError(而不是普通的Error对象或者只返回错误信息),这样客户端才能识别为GraphQL层面的错误。比如正确的写法应该是:
// 示例Resolver代码(请对照你的实际代码调整) const { GraphQLError } = require('graphql'); // 记得导入GraphQLError const loginResolver = async (_, { email, password }) => { // 查找用户 const user = await User.findOne({ email }); // 验证密码 const isPasswordValid = user ? await bcrypt.compare(password, user.password) : false; if (!user || !isPasswordValid) { // 关键:抛出带扩展信息的GraphQLError throw new GraphQLError('邮箱与密码不匹配', { extensions: { code: 'UNAUTHENTICATED', http: { status: 401 }, }, }); } // 验证通过,返回token等数据 return { token: generateAuthToken(user) }; };
验证Playground的响应
如果Resolver写对了,Playground返回的响应应该包含errors数组,类似这样:
{ "errors": [ { "message": "邮箱与密码不匹配", "extensions": { "code": "UNAUTHENTICATED", "http": { "status": 401 } } } ], "data": null }
- 如果看到这个结构,说明服务器端没问题,问题出在React客户端。
- 如果没有
errors字段,或者错误格式不对,那就是服务器端Resolver的问题,需要修改这里。
第二步:检查React客户端的错误捕获逻辑
如果服务器端已经正确返回了GraphQL错误,那大概率是客户端没正确解析graphQLErrors字段。以Apollo Client为例,很多开发者会只捕获网络错误,忽略了GraphQL层面的错误:
错误的捕获方式(只抓网络错误)
const [login] = useMutation(LOGIN_MUTATION); const handleLogin = async () => { try { const { data } = await login({ variables: { email, password } }); // 处理登录成功逻辑 } catch (error) { // 这里只会打印网络错误,GraphQL错误藏在error.graphQLErrors里 console.error('登录失败:', error); } };
正确的捕获方式(处理GraphQL错误)
const [login] = useMutation(LOGIN_MUTATION); const handleLogin = async () => { try { const { data } = await login({ variables: { email, password } }); // 处理登录成功逻辑 } catch (error) { // 优先检查GraphQL错误 if (error.graphQLErrors?.length > 0) { const loginError = error.graphQLErrors[0].message; console.log('登录错误:', loginError); // 这里就能拿到"邮箱与密码不匹配" // 把错误提示渲染到页面上 setError(loginError); } else { // 处理网络错误或其他异常 console.error('网络或系统错误:', error); setError('登录失败,请稍后重试'); } } };
如果你用的是其他GraphQL客户端(比如Relay、Urql),也要确认客户端是否正确解析了响应中的errors字段。
第三步:确定该提交到哪个GitHub仓库
- 服务器端仓库:如果Playground测试时没有返回正确的GraphQL错误结构,说明是Resolver的问题,提交到服务器端代码的仓库。
- React前端仓库:如果服务器端返回了正确的错误,但客户端捕获不到或无法展示,提交到React应用的仓库。
- 拿不准的话,可以在issue里附上GraphQL Playground的响应截图和客户端的错误日志,方便维护者快速定位。
内容的提问来源于stack exchange,提问作者Good Idea
相关产品推荐
相关产品推荐

