项目场景:
点击‘下载数据’将后端传来的表格数据下载为Excel文件
项目技术栈:react+umi+antd+procomponent
问题描述
下载的Excel表格内容为‘undefined’
原本的实现如下:
const downloadClick = async ()=>{
let params = { //请求参数
...
}
const blob = await downloadRun(params)
exportExcel(blob, '用户留存数据') //自定义的导出Excel方法
message.success('下载成功')
}
注意⚠️
这里使用umi 的useRequest
发送请求
原因分析:
接口返回的是非标准数据,并且未正确处理响应数据
在分析我的代码出错原因前,
先来回顾一下umi的useRequest:
//完整的useRequest写法
const { data, error, loading, run, cancel, refresh } = useRequest('/api/getData', {
manual: false,
formatResult: (response) => response.data,
onSuccess: (data, params) => console.log('success', data, params),
onError: (error, params) => console.log('error', error, params),
onFinally: (params, data, error) => console.log('finally', data, error),
});
参数详解
- 第一个参数:可以是一个字符串(请求的 URL),也可以是一个函数(返回一个 Promise)。
- 第二个参数:是一个配置对象,常见的属性包括:
• manual: 默认为 false,表示自动执行请求。如果设置为 true,需要手动调用 run 方法来触发请求。
• formatResult: 一个函数,用来格式化请求返回的数据。返回值将会被赋值给data。
• onSuccess: 请求成功时的回调函数。
• onError: 请求失败时的回调函数。
• onFinally: 请求结束时(无论成功还是失败)的回调函数。
返回值详解
useRequest 返回一个对象,该对象包含以下属性和方法:
• data: 请求返回的数据。通过 formatResult 处理后的数据会赋值给 data。
• error:请求发生错误时的错误对象。
• loading: 请求是否正在进行。
• run: 触发请求的方法。特别是在 manual: true的情况下,需要手动调用。
• cancel: 取消当前请求的方法。
• refresh: 重新执行上一次请求的方法。
formatResult 的作用
formatResult 的主要作用是处理接口的原始响应数据,使其符合组件所需要的格式
。如果不指定 formatResult,useRequest 会将接口返回的数据原样提供给 data。
formatResult ---> data
举个例子:
有以下场景
const { data } = useRequest('/api/getData', {
formatResult: (response) => response.data,
});
假设 /api/getData 返回的数据结构如下:
{
"data": {
"list": [ ... ],
"total": 100
}
}
在这种情况下,如果没有使用 formatResult,useRequest 返回的 data 将是整个响应对象:
{
"data": {
"list": [ ... ],
"total": 100
}
}
而如果使用了 formatResult 提取 response.data,那么 data 将只包含 response.data 的内容,即:
{
"list": [ ... ],
"total": 100
}
如果你不使用 formatResult 进行处理,而直接期望访问 data.list 或 data.total,但实际返回的是整个响应对象,这时会发现 data 为 undefined,因为数据结构不匹配。
现在,返回到我的项目中。
网络请求是:
该网络请求返回的内容是:
总结:请求返回的内容不是格式化数据时,不写formatResult,数据结构不匹配,data就undefined
解决方案:
在请求时写上formatResult
结论
通常,返回的数据为 undefined 是因为数据结构不匹配或未正确处理接口的响应数据。formatResult 的作用是确保返回的数据格式符合预期。如果你遇到数据为 undefined 的情况,首先检查接口是否正确响应数据,然后检查数据的结构,最后确保使用 formatResult 处理和提取所需的数据部分。