RTK Query钩子调用错误:登录功能实现问题求助
问题解决:RTK Query登录请求的正确实现方式
核心问题分析
登录操作属于主动提交凭证获取授权的行为,属于修改服务器状态(或触发状态校验)的操作,RTK Query中应该使用mutation而非query:
query钩子会在组件挂载时自动发起请求,不符合登录需要用户主动提交的场景mutation钩子返回手动触发的函数,仅在调用时发起请求,且符合React Hooks的调用规则
1. 修正API定义:将loginIn改为Mutation
修改requestApi中的登录端点定义,从builder.query改为builder.mutation,并更新导出的钩子名称:
export const requestApi = createApi({ reducerPath: 'requestApi', baseQuery: fetchBaseQuery({ baseUrl: 'http://localhost:5000/', prepareHeaders: (headers:any) => { headers.set('authorization', localStorage.getItem('token')); return headers; }, }), tagTypes: ['request'], endpoints: (builder) => ({ registerUser: builder.mutation<any, any>({ query: (params) => ({ url: '/auth/registration', method: 'POST', body: params, }), }), // 关键修改:将query替换为mutation loginIn: builder.mutation<any, any>({ query: (params) => ({ url: '/auth/login', method: 'POST', body: params, }), }), }), }); // 导出对应的mutation钩子 export const { useGetSortedFilmQuery, useRegisterUserMutation, useLoginInMutation, // 同步修改钩子名称 useGetInfoUserQuery, useAddFilmQuery, } = requestApi;
2. 在组件中使用useLoginInMutation钩子
和注册逻辑一致,在组件顶层获取mutation触发函数,然后在表单提交时手动调用:
export const LoginForm:FC<LoginFormProps> = (props) => { // 注册钩子保留 const [registerIn, { data: requestRegister, error: errorRegister, isError: isErrorRegister, isLoading: loadingRegister, }] = useRegisterUserMutation(); // 登录改用mutation钩子(组件顶层调用,符合Hooks规则) const [loginIn, { data: userLogin, isError: isErrorLogin, isLoading: loadLogin, error: errorLogin, }] = useLoginInMutation(); // React Hook Form 逻辑保留 const {register, handleSubmit, setError, formState: { errors, isValid },} = useForm<loginForm>({mode: 'onChange',}); // 注册函数保留 const sendRegisterForm = (element:any) => { if (Number.isFinite(+element.mailOrNumberRegistration.replace('+', ''))) { registerIn({ phoneNumber: element.mailOrNumberRegistration, password: element.passwordRegistration }); } else { registerIn({ email: element.mailOrNumberRegistration, password: element.passwordRegistration }); } }; // 登录函数修改为调用mutation触发函数 const sendLoginForm = (element:any) => { const loginParams = Number.isFinite(+element.mailOrNumberLoginIn.replace('+', '')) ? { phoneNumber: element.mailOrNumberLoginIn, password: element.passwordLogin } : { email: element.mailOrNumberLoginIn, password: element.passwordLogin }; // 手动触发登录请求,通过unwrap处理成功/失败 loginIn(loginParams) .unwrap() .then(data => { console.log('登录成功:', data); // 处理登录成功逻辑,比如存储token到localStorage localStorage.setItem('token', data.token); }) .catch(err => { console.error('登录失败:', err); // 给表单设置错误提示 setError('mailOrNumberLoginIn', { message: '账号或密码错误' }); }); }; // 表单提交处理保留 const onSubmit: SubmitHandler<loginForm> = (data) => { if (clickOnEnter === 0) { sendLoginForm(data); } if (clickOnEnter === 1) { sendRegisterForm(data); } }; // 渲染部分保留... };
关键说明
- React Hooks必须在组件顶层调用,不能嵌套在内部函数中,因此mutation钩子需放在组件最外层
mutation钩子返回的第一个参数是手动触发请求的函数,只有调用它时才会发起登录请求,避免了组件挂载时自动请求的问题- 使用
unwrap()可以直接获取请求成功的数据,或捕获请求失败的错误,方便后续逻辑处理
内容的提问来源于stack exchange,提问作者Максим Дмитриевич
相关产品推荐
相关产品推荐

