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

React函数组件:如何在switch执行前通过fetch加载数据?

解决React组件异步数据加载问题的正确方式

你遇到的核心问题是没搞清楚React函数组件的渲染逻辑:组件渲染是同步执行的,而fetch是异步操作,用普通变量存储异步数据的话,请求完成后组件不会自动重新渲染,而且初始值为空,必然触发undefined错误。把switch放进then里返回Promise也不行,因为React组件必须返回React元素,不能返回Promise。

正确的做法是用React的**状态管理(useState)和副作用钩子(useEffect)**来处理异步数据,具体修改如下:

完整修改后的代码

import { useState, useEffect } from 'react';

const Table = ({ route, OnAccessBranch, Branche }) => {
  // 用状态管理异步数据、加载状态、错误状态
  const [tableData, setTableData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  // 用useEffect发起异步请求,组件挂载时执行一次
  useEffect(() => {
    fetch("http://localhost:3000/GetTableData")
      .then(response => {
        if (!response.ok) {
          throw new Error('请求失败');
        }
        return response.json();
      })
      .then(Data => {
        setTableData(Data); // 更新状态,触发组件重新渲染
        setLoading(false);
      })
      .catch(err => {
        setError(err.message);
        setLoading(false);
      });
  }, []); // 空依赖数组,只在组件挂载时执行一次

  // 加载中状态提示
  if (loading) {
    return <div>加载中...</div>;
  }

  // 错误状态提示
  if (error) {
    return <div>出错了:{error}</div>;
  }

  // 根据route匹配对应数据
  let items = [];
  let colNames = [];

  switch(route){
    case "Branches":
      items = tableData[0] || []; // 加默认值避免空数据报错
      colNames = items.length > 0 ? Object.keys(items[0]) : [];
      break;
    // 可在此添加Services、Guichets等其他case的处理逻辑
    default:
      items = [];
      colNames = [];
  }

  // 空数据提示
  if (items.length === 0) {
    return <div>暂无数据</div>;
  }

  // 渲染表格
  return (
    <table className="f6 w-100 ml4 mt2 outline">
      <thead>
        <tr>
          {colNames.map((Colonnes, indexMetaData) => (
            <th className="fw6 bb b--black-20 pb3 pr3 bg-white tl" key={indexMetaData}> 
              { Colonnes.toString().toUpperCase() } 
            </th>
          ))}
        </tr>
      </thead>
      <tbody className="lh-copy">
        {items.map((Ligne, indexRow) => (
          <tr key={indexRow}>
            {Object.entries(Ligne).map((Cell, indexCell) => (
              <td className="pv3 pr3 bb b--black-20" key={indexCell}> { Cell[1] }</td>
            ))}
            <td className="pv3 pr3 bb b--black-20">
              <input 
                type="button" 
                value="Supprimer" 
                name={Ligne.REF} // 直接用当前行数据,比items[indexRow].REF更安全
                className="white b pv2 ph3 bg-red hover-bg-mid-gray bn br2 hover-shadow-inner f3" 
              />
            </td>
            <td className="pv3 pr3 bb b--black-20">
              <input 
                onClick={OnAccessBranch} 
                type="button" 
                value="Guichets" 
                name={Ligne.REF} 
                className="white b pv2 ph3 bg-blue hover-bg-mid-gray bn br2 hover-shadow-inner f3" 
              />
            </td>
            <td className="pv3 pr3 bb b--black-20">
              <input 
                onClick={OnAccessBranch} 
                type="button" 
                value="Services" 
                name={Ligne.REF} 
                className="white b pv2 ph3 bg-green hover-bg-mid-gray bn br2 hover-shadow-inner f3" 
              />
            </td>
          </tr>
        ))}
      </tbody>
    </table>
  );
};

关键修改说明

  • 用状态存储异步数据:useState定义的tableData会在数据更新时自动触发组件重新渲染,保证渲染逻辑能拿到最新数据。
  • 用useEffect处理异步请求:确保请求在组件挂载后执行,且不会重复触发(空依赖数组)。
  • 增加状态边界处理:加载中、错误、空数据的提示,避免出现undefined错误。
  • 安全取值:给items和colNames加默认值,防止数据为空时调用Object.keys或map报错。

内容的提问来源于stack exchange,提问作者3idoudi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 03:53:20