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

React组件:如何将componentDidMount数据加载移至render前执行?

在React类组件render前完成数据加载的实现方案

你当前的组件在componentDidMount中加载数据,这个生命周期钩子是在组件首次渲染完成后执行的,所以数据会在render之后才获取。要在render前完成数据加载,可以参考以下几种方案:

方案一:构造函数中发起异步请求(推荐)

构造函数是组件初始化时第一个执行的方法,在render之前触发。虽然构造函数不能直接用async/await,但可以通过.then()或单独封装异步方法来处理数据请求,同时添加加载状态控制渲染内容:

修改后的完整代码示例:

import React from 'react';
import { withRouter } from 'react-router-dom';
import { connect } from 'react-redux';
import { Chart } from 'react-google-charts';
import { loadAttivita } from '../../services/attivita';

let columns = [
  { type: 'string', label: 'Task ID' },
  { type: 'string', label: 'Task Name' },
  { type: 'string', label: 'Resource' },
  { type: 'date', label: 'Start Date' },
  { type: 'date', label: 'End Date' },
  { type: 'number', label: 'Duration' },
  { type: 'number', label: 'Percent Complete' },
  { type: 'string', label: 'Dependencies' },
];

export const options = {
  height: 400,
  gantt: {
    trackHeight: 30,
  },
};

class GaantView extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      rows: [],
      isLoading: true, // 新增加载状态
      key: 0,
    };
    // 初始化时触发数据加载
    this.fetchData();
  }

  // 封装异步数据加载方法
  fetchData = async () => {
    try {
      const valori = await loadAttivita();
      // 格式化数据并更新state
      const formattedRows = valori.map(item => [
        '2014Spring',
        item.Descrizione,
        'autumn',
        new Date(2014, 2, 22),
        new Date(2014, 5, 20),
        null,
        100,
        null,
      ]);
      this.setState({
        rows: formattedRows,
        isLoading: false,
      });
    } catch (err) {
      console.error('数据加载失败:', err);
      this.setState({ isLoading: false });
    }
  };

  render() {
    const { isLoading, rows } = this.state;
    // 加载中显示提示,避免空图表
    if (isLoading) {
      return <div style={{ color: 'white', textAlign: 'center' }}>加载中...</div>;
    }
    return (
      <div>
        <p style={{ color: 'white', alignContent: 'center' }}>Diagramma Gaant</p> {' '}
        <Chart chartType="Gantt" width="100%" height="100%" data={[columns, ...rows]} options={options} />
      </div>
    );
  }
}

function mapStateToProps(state) {
  return {
    isFetching: state.auth.isFetching,
    isAuthenticated: state.auth.isAuthenticated,
    errorMessage: state.auth.errorMessage,
  };
}

export default withRouter(connect(mapStateToProps)(GaantView));

说明:

  • 修复了你原代码中未更新state的问题(原代码将数据push到全局变量,但render使用的是state中的rows,导致图表无法显示数据)
  • 通过isLoading状态控制渲染内容,避免首次render时显示空图表

方案二:将数据请求移到父组件

如果希望子组件render时直接拥有数据,可以把加载逻辑放到父组件,父组件加载完成后再渲染GaantView:

父组件示例

import React from 'react';
import GaantView from './GaantView';
import { loadAttivita } from '../../services/attivita';

class ParentComponent extends React.Component {
  state = {
    attivitaData: null,
    isLoading: true,
  };

  async componentDidMount() {
    const valori = await loadAttivita();
    this.setState({
      attivitaData: valori,
      isLoading: false,
    });
  }

  render() {
    const { isLoading, attivitaData } = this.state;
    if (isLoading) {
      return <div style={{ color: 'white', textAlign: 'center' }}>加载中...</div>;
    }
    return <GaantView attivitaData={attivitaData} />;
  }
}

修改后的GaantView组件

class GaantView extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      rows: this.formatData(props.attivitaData),
      key: 0,
    };
  }

  // 格式化数据方法
  formatData = (data) => {
    return data.map(item => [
      '2014Spring',
      item.Descrizione,
      'autumn',
      new Date(2014, 2, 22),
      new Date(2014, 5, 20),
      null,
      100,
      null,
    ]);
  };

  // 监听props变化,重新格式化数据
  componentDidUpdate(prevProps) {
    if (prevProps.attivitaData !== this.props.attivitaData) {
      this.setState({
        rows: this.formatData(this.props.attivitaData),
      });
    }
  }

  render() {
    return (
      <div>
        <p style={{ color: 'white', alignContent: 'center' }}>Diagramma Gaant</p> {' '}
        <Chart chartType="Gantt" width="100%" height="100%" data={[columns, ...this.state.rows]} options={options} />
      </div>
    );
  }
}

说明:这种方式符合组件职责分离原则,子组件只负责渲染,数据请求逻辑交给父组件处理。

不推荐的方案:使用UNSAFE_componentWillMount

React已将componentWillMount标记为不安全生命周期(重命名为UNSAFE_componentWillMount),它可能在服务端渲染中被多次调用,且无法可靠处理异步错误,官方强烈不推荐使用,但如果一定要在render前执行,可以参考:

async UNSAFE_componentWillMount() {
  const valori = await loadAttivita();
  const formattedRows = valori.map(item => [
    '2014Spring',
    item.Descrizione,
    'autumn',
    new Date(2014, 2, 22),
    new Date(2014, 5, 20),
    null,
    100,
    null,
  ]);
  this.setState({ rows: formattedRows });
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 08:35:05