React-Query中useMutation实现注册多请求流程的最优方案咨询
React-Query 注册流程优化方案
先指出你原代码里的几个明显问题:
onSuccess回调里用了await但没标记async,会直接触发语法错误checkDuple函数没有返回API的响应结果,导致onSuccess里拿不到判断邮箱是否重复的依据- 直接操作DOM节点(
warning.current)不符合React状态管理的思路,应该用组件状态控制提示文本 - 命名混乱,比如
loginQuery实际是检查邮箱重复的mutation,极易误导后续维护 - 完全缺失错误处理逻辑,不管是检查邮箱还是注册请求失败,用户都看不到任何反馈
下面是优化后的实现思路和代码:
优化核心点
- 拆分两个独立的
useMutation,分别负责「检查邮箱重复」和「用户注册」,职责更清晰 - 用React状态管理错误提示,替代直接操作DOM
- 给每个mutation加上错误处理逻辑,捕获请求失败的场景
- 确保邮箱检查通过后,再手动触发注册mutation
- 规范变量和函数命名,提升代码可读性
完整优化代码
import { useMutation } from '@tanstack/react-query'; import axios from 'axios'; import { useState } from 'react'; import { useNavigate } from 'react-router-dom'; const RegisterPage = () => { const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); const [errorMsg, setErrorMsg] = useState(''); const navigate = useNavigate(); // 检查邮箱是否重复的mutation const { mutate: checkEmailDuplicate, isLoading: isChecking } = useMutation({ mutationFn: async (targetEmail) => { const res = await axios.post('http://localhost:8080/join/duple', { id: targetEmail }); // 假设接口返回true表示邮箱可用,false表示已重复 return res.data; }, onSuccess: (isAvailable) => { if (isAvailable) { // 邮箱可用,触发注册请求 registerUser({ id: email, pass: password }); setErrorMsg(''); } else { setErrorMsg('抱歉,该邮箱已被注册'); } }, onError: () => { setErrorMsg('检查邮箱状态失败,请稍后重试'); } }); // 用户注册的mutation const { mutate: registerUser, isLoading: isRegistering } = useMutation({ mutationFn: async (userData) => { const res = await axios.post('http://localhost:8080/join/signUp', userData); return res.data; }, onSuccess: (token) => { localStorage.setItem('token', token); navigate('/todo'); }, onError: () => { setErrorMsg('注册失败,请稍后重试'); } }); // 表单提交处理函数 const handleSubmit = (e) => { e.preventDefault(); setErrorMsg(''); // 先触发邮箱重复检查 checkEmailDuplicate(email); }; return ( <form onSubmit={handleSubmit}> <input type="email" value={email} onChange={(e) => setEmail(e.target.value)} placeholder="请输入邮箱" disabled={isChecking || isRegistering} /> <input type="password" value={password} onChange={(e) => setPassword(e.target.value)} placeholder="请输入密码" disabled={isChecking || isRegistering} /> {errorMsg && <p style={{ color: 'red' }}>{errorMsg}</p>} <button type="submit" disabled={isChecking || isRegistering}> {isChecking ? '检查邮箱中...' : isRegistering ? '注册中...' : '注册'} </button> </form> ); }; export default RegisterPage;
额外说明
- 用
isLoading状态控制按钮和输入框的禁用状态,避免用户重复提交请求 - 所有提示信息都通过React状态管理,完全符合组件化开发思维
- 每个mutation都单独处理成功和失败场景,用户体验更友好
- 拆分后的两个mutation可以单独复用,后续扩展功能更灵活
内容的提问来源于stack exchange,提问作者Boris Park
相关产品推荐
相关产品推荐

