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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 03:13:25