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

为何React项目中会出现‘Property 'data' does not exist on type 'void'’错误?

解决React Query中useMutation的mutate返回void类型错误

错误信息

ERROR in src/pages/login/index.tsx:63:22
TS2339: Property 'data' does not exist on type 'void'.
    61 |           password: loginData.password,
    62 |         });
  > 63 |         if (response.data){
       |                      ^^^^
    64 |           const accessToken = response.data.access_token;
    65 |           const refreshToken = response.data.refresh_token;
    66 |           localStorage.setItem("accessToken", accessToken);'

问题原因

React Query的mutate函数不返回Promise,它仅异步触发请求但不支持await语法,因此你用const response = await UserLogin(...)得到的response是void类型,自然不存在data属性。

解决方案

方案1:使用mutateAsync替代mutate

mutateAsync是mutate的Promise版本,支持用await直接获取请求返回值,修改代码如下:

// 替换原有的mutate为mutateAsync
const { mutateAsync: UserLogin } = useMutation({
  mutationFn: getLoginData,
});

// handleLogin逻辑保持不变,因为mutateAsync返回Promise
const handleLogin = async (e: React.FormEvent) => {
  e.preventDefault();
  if (checkUserValidation()) {
    try {
      const response = await UserLogin({
        email: loginData.email,
        password: loginData.password,
      });
      if (response.data){
        const accessToken = response.data.access_token;
        const refreshToken = response.data.refresh_token;
        localStorage.setItem("accessToken", accessToken);
        localStorage.setItem("refreshToken", refreshToken);
        setInterval(refreshAccessToken, 60000);
      } else {
        console.error("登录错误:无响应数据");
      }
    } catch (error) {
      console.error("登录错误:", error);
    }
  }
};

方案2:通过onSuccess回调处理结果

把token存储逻辑移到useMutation的onSuccess回调中,这是React Query推荐的异步操作处理方式:

const { mutate: UserLogin } = useMutation({
  mutationFn: getLoginData,
  onSuccess: (response) => {
    if (response.data){
      const accessToken = response.data.access_token;
      const refreshToken = response.data.refresh_token;
      localStorage.setItem("accessToken", accessToken);
      localStorage.setItem("refreshToken", refreshToken);
      setInterval(refreshAccessToken, 60000);
    } else {
      console.error("登录错误:无响应数据");
    }
  },
  onError: (error) => {
    console.error("登录错误:", error);
  }
});

// 修改handleLogin,直接调用mutate即可
const handleLogin = (e: React.FormEvent) => {
  e.preventDefault();
  if (checkUserValidation()) {
    UserLogin({
      email: loginData.email,
      password: loginData.password,
    });
  }
};

额外修复:请求格式问题

你的getLoginData函数存在矛盾:使用FormData但设置了Content-Type: application/json,会导致后端无法正确解析请求。根据后端要求二选一:

如果后端接收JSON格式

export const getLoginData = async (loginData: LoginData) => {
  try {
    return await axiosClient.post("/auth/authenticate", loginData,
    {
      headers:{
        // axios会自动设置Content-Type为application/json,无需手动指定
        'Authorization': `Bearer ${localStorage.getItem('accessToken')}`
      },
    });
  } catch (error) {
    console.error("API错误:", error);
    throw error;
  }
};

如果后端接收FormData格式

export const getLoginData = async (loginData: LoginData) => {
  try {
    const loginDatas = new FormData();
    loginDatas.append("email", loginData.email);
    loginDatas.append("password", loginData.password);
    return await axiosClient.post("/auth/authenticate", loginDatas,
    {
      headers:{
        // axios会自动设置Content-Type为multipart/form-data,无需手动指定
        'Authorization': `Bearer ${localStorage.getItem('accessToken')}`
      },
    });
  } catch (error) {
    console.error("API错误:", error);
    throw error;
  }
};

内容的提问来源于stack exchange,提问作者mikasa akerman

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 00:12:03