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

ReactJS项目中Modal弹窗表格数据为空问题求助

React项目Modal表格数据不显示问题排查

我正在开发一个ReactJS项目,通过Axios调用API获取数据并在Modal弹窗中展示。点击“E Score”按钮后Treemap图表能正常显示,但表格始终为空,尽管API已正确返回对应数据。以下是相关代码及问题截图:

const ChartSmallDoughnutChart3 = ({ aux, name, variable }) => {
  const { themeValues } = useSelector((state) => state.settings);
  const chartContainer = useRef(null);
  const legendRef = useRef(null);
  const [semiFullExample, setSemiFullExample] = useState(false);
  const [keywordsList, setKeywords] = useState();
  const [detailsList, setDetails] = useState();
  const couleur = 'rgb(75, 192, 192)';

  function timeout(delay) {
    return new Promise((res) => setTimeout(res, delay));
  }

  const getDetails = async () => {
    const queryResult = await axios.post(GRAPHQL_API, {
      query: GET_KEYWORDS_DETAILS,
      variables: {
        company: name,
        category: variable,
      },
    });
    const result = queryResult.data.data.getDetailsKeyword;
    setDetails(result);
    console.log(result);
  };

  const handleModalLoad = async (param1, param2) => {
    const getKeywordsList = async () => {
      const queryResult = await axios.post(GRAPHQL_API, {
        query: GET_KEYWORDS_LIST,
        variables: {
          company: param1,
          category: param2,
        },
      });
      const result = queryResult.data.data.getKeywords;
      setKeywords(result);
    };
    getKeywordsList();
    setSemiFullExample(true);
    await timeout(1000);
    getDetails();
    // setSemiFullExample(true);
  };

const CustomSmallLegendDoughnutPlugin = React.useMemo(() => {
    return {
      id: 'htmlLegendDoughnutSmall',
      afterUpdate: (chart, args, options) => {
        const items = chart.options.plugins.legend.labels.generateLabels(chart);
        ReactDOM.render(
          <>
            {items.map((legend) => {
              const { strokeStyle, text, index, hidden } = legend;
              return (
                <div key={`customLegend${index}`}>
                  <div className="text-small text-muted text">{text}</div>
                  <Button variant="link" className="mb-1" onClick={() => handleModalLoad(name, variable)}>
                    {' '}
                    <div className="cta-3 text-info value">E Score</div>
                  </Button>
                </div>
              );
            })}
          </>,
          legendRef.current
        );
      },
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [name, variable]);

  return (
    <>
      <Row className="g-0 d-flex w-100">
        <Col ref={legendRef} className="sh-8 d-flex flex-column justify-content-center custom-legend-container" />
        <Col xs="auto">
          <canvas ref={chartContainer} className="sw-8 sh-8" />
        </Col>
      </Row>
      <Modal show={semiFullExample} onHide={() => setSemiFullExample(false)} size="semi-full" scrollable centered>
        <Modal.Header closeButton>
          <Modal.Title>E Score Details</Modal.Title>
        </Modal.Header>
        <Modal.Body>
          <TreemapChart aux={keywordsList} color={couleur} />
          <section className="scroll-section" id="stripedRows">
            <>
              <h2 className="small-title">ESG Details</h2>
              <Table striped>
                <thead>
                  <tr>
                    <th scope="col">Paragraph</th>
                    <th scope="col">Link</th>
                    <th scope="col">Topic</th>
                    <th scope="col">Keywords</th>
                    <th scope="col">Key-Words</th>
                    <th scope="col">Sentiment</th>
                    <th scope="col">Sentiment Score</th>
                    <th scope="col">Paraphrase</th>
                    <th scope="col">Topic Score</th>
                  </tr>
                </thead>
                <tbody>
                  {detailsList?.map((item, i) => (
                    <tr key={i}>
                      <td>{item.Paragraph}</td>
                      <td>{item.Link}</td>
                      <td>{item.Topic}</td>
                      <td>{item.keywords}</td>
                      <td>{item.key_words}</td>
                      <td>{item.Sentiment}</td>
                      <td>{item.Sentiment_Score}</td>
                      <td>{item.Paraphrase}</td>
                      <td>{item.Topic_Score}</td>
                    </tr>
                  ))}
                </tbody>
              </Table>
            </>
          </section>
        </Modal.Body>
        <Modal.Footer>
          <Button onClick={() => setSemiFullExample(false)}>Close</Button>
        </Modal.Footer>
      </Modal>
    </>
  );
};

Modal问题截图
Axios API返回结果截图


问题排查与解决
  • 字段名匹配问题
    检查API返回的字段名与表格渲染时使用的字段是否完全一致。从截图看API返回的字段可能存在大小写或命名格式差异,比如确认Paragraph、Link等字段是否和接口返回的键名完全匹配,避免因字段名拼写错误导致数据无法渲染。

  • 异步逻辑顺序问题
    当前代码用固定1秒延迟调用getDetails,这种方式不可靠,可能导致Modal打开时detailsList还未更新。修改handleModalLoad,确保数据请求完成后再打开Modal:

    const handleModalLoad = async (param1, param2) => {
      // 先获取keywordsList
      const keywordsRes = await axios.post(GRAPHQL_API, {
        query: GET_KEYWORDS_LIST,
        variables: { company: param1, category: param2 },
      });
      setKeywords(keywordsRes.data.data.getKeywords);
      
      // 再获取details数据
      const detailsRes = await axios.post(GRAPHQL_API, {
        query: GET_KEYWORDS_DETAILS,
        variables: { company: name, category: variable },
      });
      setDetails(detailsRes.data.data.getDetailsKeyword);
      
      // 所有数据获取完成后打开Modal
      setSemiFullExample(true);
    };
    
  • 初始状态设置问题
    detailsList初始值为undefined,虽然用了可选链?.map,但如果API返回空数组,表格仍会显示空白。将初始状态设为空数组:

    const [detailsList, setDetails] = useState([]);
    

    这样即使没有数据,表格也能显示表头和空行,更符合预期。

  • React状态更新异步性问题
    状态更新是异步的,若Modal已打开但状态还未更新,可通过useEffect监听detailsList变化,确保组件能重新渲染。不过通常React会自动处理状态更新后的重渲染,但若存在复杂逻辑,可添加监听:

    useEffect(() => {
      if (semiFullExample && detailsList) {
        // 可添加额外的渲染逻辑
      }
    }, [semiFullExample, detailsList]);
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 02:01:11