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

React函数结果无法渲染:表格报错与数据展示问题

问题分析与解决方案

核心错误原因

  1. Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'indexOf')
    你错误地将Stock组件当作普通类用new Stock()实例化,但它本质是React组件,不能通过new创建实例。同时Stock返回的是异步函数的Promise对象,React尝试渲染这个Promise时触发了内部错误。

  2. 表格不允许文本子节点
    {loading && "Loading..."}直接将文本作为<table>的直接子元素,而HTML规范中<table>的直接子元素只能是<thead>、<tbody>、<tfoot>等,文本节点属于非法子元素。

  3. 数据无法渲染到页面
    你在map中用同步变量存储异步获取的数据,Promise完成后更新变量不会触发React重新渲染;同时map中的JSX没有return,导致根本不会生成表格行。


修复步骤

1. 重构Stock.js为工具函数

因为Stock不需要渲染UI,只是获取数据,所以改成纯异步工具函数:

import { FetchStockPrice, FetchStockDividend } from './StockData';

export const getStockData = async (stockTicker, shares) => {
  const price = await FetchStockPrice(stockTicker);
  const div = await FetchStockDividend(stockTicker);
  const divAmnt = (div * price).toFixed(2);
  const annual = divAmnt * shares;
  
  return {
    price: price.toFixed(2),
    divYield: div,
    divAmnt: divAmnt,
    annual: annual
  };
};

2. 修复ShowStock.js的渲染逻辑

  • 将加载提示移到表格外,避免非法子节点
  • 用状态存储所有股票的详细数据,批量异步获取
  • 修正JSX语法错误,添加必要的return和key属性
import { useState, useEffect } from 'react';
import { UserAuth } from './你的Auth路径'; // 补充实际路径
import { collection } from 'firebase/firestore'; // 补充导入
import { useCollectionData } from 'react-firebase-hooks/firestore'; // 补充导入
import { getStockData } from './Stock';

const ShowStock = () => {
  const { user } = UserAuth();
  const [stockDetails, setStockDetails] = useState({});
  const [isLoadingDetails, setIsLoadingDetails] = useState(false);
  const dir = `users/${user.uid}/invList`;
  const q = collection(db, dir);
  const [docs, loading, error] = useCollectionData(q);

  // 批量获取所有股票数据
  useEffect(() => {
    if (!loading && docs) {
      setIsLoadingDetails(true);
      const fetchAllData = async () => {
        const detailsMap = {};
        for (const stock of docs) {
          detailsMap[stock.stockTicker] = await getStockData(stock.stockTicker, 1);
        }
        setStockDetails(detailsMap);
        setIsLoadingDetails(false);
      };
      fetchAllData();
    }
  }, [docs, loading]);

  // 加载状态处理
  if (loading || isLoadingDetails) {
    return <div>Loading...</div>;
  }

  // 错误处理
  if (error) {
    return <div>Error: {error.message}</div>;
  }

  return (
    <div>
      <table className="table table-striped">
        <thead>
          <tr>
            <th scope="col">Stock Ticker</th>
            <th scope="col">Price</th>
            <th scope="col">Dividend Yeild %</th>
            <th scope="col">Dividend Amount Annually</th>
            <th scope="col">Annual Dividend Profits</th>
          </tr>
        </thead>
        <tbody>
          {docs?.map((stock) => {
            const details = stockDetails[stock.stockTicker];
            if (!details) return null;
            
            return (
              <tr key={stock.stockTicker}>
                <th>{stock.stockTicker}</th>
                <td>{details.price}</td>
                <td>{details.divYield}</td>
                <td>{details.divAmnt}</td>
                <td>{details.annual}</td>
              </tr>
            );
          })}
        </tbody>
      </table>
    </div>
  );
};

export default ShowStock;

额外注意点

  • React中要用className替代class(class是JS关键字)
  • 遍历列表时必须添加key属性,帮助React识别元素变化
  • 原代码中let divA =存在语法错误,已在重构中消除

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 14:10:45