【问题标题】:ReactJS - Which Component LifeCycle method should be used to create table and populate with data after AJAX callReactJS - 应该使用哪个组件生命周期方法来创建表并在 AJAX 调用后填充数据
【发布时间】:2018-06-14 14:42:57
【问题描述】:

我试图弄清楚如何在 AJAX 调用发生并检索数据后显示和填充数据表。

用户从 AppointmentHome 开始,它有一个日期选择器,在那里他们可以选择他们想要检索的约会日期。一旦他们选择日期并单击搜索,就会调用 getAppointmentData() 并检索数据。

目前,我在 getAppointmentData() 的回调中将数据检索到 var 约会数组中,然后在回调中调用 CreateTableRows(),以便在检索到数据之后而不是之前调用它。

现在,我很难弄清楚如何在 AppointmentList 的呈现中获取 CreateTableRows() 的输出,以便它与表的其余部分一起填充。我相信我可能需要将一些代码移动到一些生命周期方法中,但我被困在如何从一个组件移动到下一个组件而不会弄乱检索数据。

var appointmentArray = null;
var table;

function getAppointmentData(){
  window.getAppointments(date, 'callback');
}

window.callback = function(objects){
  appointmentArray = objects;
  table = createTableRows();
}

function createTableRows(){
  var output = "<tbody>";
  for (var i = 0; i < 1; i++){
    output += "<tr><th scope='row'>"+appointmentArray[i]+ "</th></tr>";
  }
  output += "</tbody>";
  return output;
}


export class AppointmentList extends React.Component {
  constructor(props){
    super(props);
  }

  render(){
    return(
      <div className = "appointment-table">
        <table className="table table-hover">
          <thead>
            <tr>
              <th scope="col">Patient Name</th>
              <th scope="col">Time</th>
              <th scope="col">Duration</th>
              <th scope="col">Provider</th>
              <th scope="col">Appointment Status</th>
            </tr>
          </thead>
        </table>
      </div>
    );
  }
}

export class AppointmentHome extends React.Component {
  constructor(props){
    super(props);

    this.handleClick = this.handleClick.bind(this);
  }

  handleClick(){
    getAppointmentData();
  }

  render(){
    return(
      <div>
        <h3> Appointment Search </h3>
        <div className = 'search'>
          <h3> Date </h3>
          <Calendar />
          <div className = 'searchButton'>
            <Link to="appointments">
                <RaisedButton label="Search" onClick = {this.handleClick}/>
            </Link>
          </div>
        </div>
      </div>
    );
  }
}

【问题讨论】:

    标签: reactjs


    【解决方案1】:

    Facebook 推荐的生命周期方法是componentDidMount。引用自official lifecycle documentation

    componentDidMount() 在组件安装后立即调用。需要 DOM 节点的初始化应该放在这里。 如果您需要从远程端点加载数据,这是一个实例化网络请求的好地方。

    请注意,在装载后 加载数据意味着在您的渲染方法中,您必须注意数据尚未加载的情况。通常,这是通过一个条件语句来完成的,该语句在没有数据时呈现微调器或类似的东西,并在可用时呈现实际数据。

    约会示例

    虽然这(希望)回答了您关于使用哪种生命周期方法的问题,但实际上与您的情况无关,因为您是在用户单击按钮后加载数据。在这种情况下,您可以在点击处理程序方法中执行此操作,并提供一个设置组件状态的回调函数。

    对于您的示例,我建议向 AppointmentHome 组件添加一个状态,该状态在加载约会数据后将其添加到其状态,并将该数据作为道具提供给 AppointmentList 组件。

    像这样:

    class AppointmentHome extends React.Component {
      constructor(props) {
        super(props);
    
        this.handleClick = this.handleClick.bind(this);
        this.state = {
          appointments: null,
          isLoading: false
        };
      }
    
      handleClick() {
        this.setState({ appointments: null, isLoading: true });
        getAppointmentData(appointments =>
          this.setState({ appointments, isLoading: false })
        );
      }
    
      render() {
        const { appointments, isLoading } = this.state;
        return (
          <div>
            <div className="search">
              <button onClick={this.handleClick}>Search</button>
            </div>
            {isLoading && <div>Please wait...</div>}
            {appointments && <AppointmentList appointments={appointments} />}
          </div>
        );
      }
    }
    

    一些注意事项:

    • 为了简洁起见,我在您的代码中省略了布局组件(MaterialUI?)和 react-router 内容
    • 在加载数据时,组件的状态会获得一个 isLoading 标志,我用它来显示“请稍候”消息
    • AppointmentList 仅在该州有约会时才会呈现 - 这就是 appointments &amp;&amp; 所做的

    约会列表

    AppointmentList 可能看起来像这样:

    class AppointmentList extends React.Component {
      constructor(props) {
        super(props);
      }
    
      render() {
        const { appointments } = this.props;
        return (
          <div className="appointment-table">
            <table className="table table-hover">
              <thead>
                <tr>
                  <th scope="col">Patient Name</th>
                  <th scope="col">Time</th>
                  <th scope="col">Duration</th>
                  <th scope="col">Provider</th>
                  <th scope="col">Appointment Status</th>
                </tr>
              </thead>
              <tbody>
                {appointments.map((appointment, i) => (
                  <tr key={`appointment${i}`}>
                    <td scope="col">{appointment.patientName}</td>
                    <td scope="col">{appointment.time}</td>
                    <td scope="col">{appointment.duration}</td>
                    <td scope="col">{appointment.provider}</td>
                    <td scope="col">{appointment.appointmentStatus}</td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        );
      }
    }
    

    如您所见,无需像您尝试在代码中那样将任何 HTML 代码连接成字符串,这一切都由组件优雅地处理:

    • 约会数组是组件的一个道具
    • 映射数组为每个约会创建一个表格行

    加载 JSONP 数据

    您正在使用 JSONP 从您的 API 加载数据,大概是为了规避跨源资源共享限制。

    这很好,但是您需要能够将任意回调函数传递给执行 JSONP 魔法的函数。如果您按照代码示例中的方式使用全局变量,它将无法正常工作,因为 AppointmentApp 很难与之连接。

    您可以使用another StackOverflow question中建议的这个解决方案:

    function jsonp(url, callback) {
        var callbackName = 'jsonp_callback_' + Math.round(100000 * Math.random());
        window[callbackName] = function(data) {
            delete window[callbackName];
            document.body.removeChild(script);
            callback(data);
        };
    
        var script = document.createElement('script');
        script.src = url + (url.indexOf('?') >= 0 ? '&' : '?') + 'callback=' + callbackName;
        document.body.appendChild(script);
    }
    

    把它们放在一起

    看看我创建的这个代码沙箱,它显示了正在运行的代码:

    https://codesandbox.io/s/j3j31qvq2v

    【讨论】:

    • 在 AppointmentHome 或 AppointmentList 中会调用 componentDidMount() 吗?如果你能提供一个例子,那就太好了!
    • 关于您的问题的实际棘手部分是您使用的是全局回调,大概是因为您调用的 API 使用的是 JSONP,对吗?
    • 那么,我的回答有帮助吗?如果是,请采纳
    猜你喜欢
    • 2019-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多