You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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,提问作者Максим Дмитриевич

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 10:07:49