React中使用async/await函数返回值:避免多useState处理多表头场景
解决React中异步函数渲染Promise的优化方案
首先修正你代码里的小问题:formdata应该和定义的formData大小写一致,否则会触发变量未定义错误。
直接在JSX中调用async函数会返回Promise,无法直接渲染成文本。针对多ID请求的场景,不用逐个创建useState,推荐以下几种更优方案:
方案1:自定义复用Hook
封装一个专门获取员工姓名的Hook,把请求逻辑和状态管理抽离出来,每个ID调用这个Hook即可,避免重复编写状态逻辑:
import { useState, useEffect } from 'react'; function useEmployeeName(user_Id) { const [name, setName] = useState('加载中...'); const [loading, setLoading] = useState(true); useEffect(() => { const fetchName = async () => { try { const formData = { user_Id }; const result = await apiResponse("getEmployeeNameByEmpId", "Post", formData); setName(result); } catch (err) { setName('获取失败'); console.error(err); } finally { setLoading(false); } }; fetchName(); }, [user_Id]); return { name, loading }; } // 使用示例 function TableHeader() { const { name: name16 } = useEmployeeName(16); const { name: name23 } = useEmployeeName(23); return ( <tr> <th>{name16}</th> <th>{name23}</th> </tr> ); }
方案2:批量预加载+缓存
如果提前知道所有需要查询的user_id,建议一次性批量请求,把结果存在一个映射对象中,渲染时直接读取,减少请求次数:
import { useState, useEffect } from 'react'; function TableHeader() { const [employeeNames, setEmployeeNames] = useState({}); const [loading, setLoading] = useState(true); // 所有需要的user_id集合 const userIds = [16, 23, 45]; useEffect(() => { const fetchAllNames = async () => { try { // 如果接口支持批量查询,直接传数组更高效 const result = await apiResponse("getEmployeeNamesByEmpIds", "Post", { userIds }); // 转成{id: name}的格式方便读取 const nameMap = userIds.reduce((map, id) => { map[id] = result.find(item => item.user_Id === id)?.name || '未知'; return map; }, {}); setEmployeeNames(nameMap); } catch (err) { console.error(err); // 失败时给默认值 const defaultMap = userIds.reduce((map, id) => { map[id] = '获取失败'; return map; }, {}); setEmployeeNames(defaultMap); } finally { setLoading(false); } }; fetchAllNames(); }, []); if (loading) return <tr><th colSpan={userIds.length}>加载中...</th></tr>; return ( <tr> {userIds.map(id => ( <th key={id}>{employeeNames[id]}</th> ))} </tr> ); }
如果接口不支持批量查询,也可以用Promise.all并行请求,再转成映射对象:
// 替换fetchAllNames里的逻辑 const fetchAllNames = async () => { try { const promises = userIds.map(id => { const formData = { user_Id: id }; return apiResponse("getEmployeeNameByEmpId", "Post", formData); }); const results = await Promise.all(promises); const nameMap = userIds.reduce((map, id, index) => { map[id] = results[index] || '未知'; return map; }, {}); setEmployeeNames(nameMap); } catch (err) { // 错误处理同上 } };
方案3:封装独立组件
把每个表头单元格做成单独组件,内部处理请求逻辑,复用性更强:
import { useState, useEffect } from 'react'; function EmployeeHeaderCell({ userId }) { const [name, setName] = useState('加载中...'); useEffect(() => { const fetchName = async () => { try { const formData = { user_Id: userId }; const result = await apiResponse("getEmployeeNameByEmpId", "Post", formData); setName(result); } catch (err) { setName('获取失败'); console.error(err); } }; fetchName(); }, [userId]); return <th>{name}</th>; } // 使用示例 function TableHeader() { return ( <tr> <EmployeeHeaderCell userId={16} /> <EmployeeHeaderCell userId={23} /> <EmployeeHeaderCell userId={45} /> </tr> ); }
额外优化建议
- 给
apiResponse添加缓存逻辑,比如用Map存储已请求过的user_id和对应的姓名,避免重复请求同一个ID。 - 处理请求失败的情况,给用户友好的提示,而不是空白或控制台报错。
内容的提问来源于stack exchange,提问作者dev321
相关产品推荐
相关产品推荐

