0

我有一个带有 3 个选项卡的反应组件,每个选项卡都包含一个数据表,该数据表将根据活动选项卡填充 API 调用结果。所以每次都会有一个参数,我通过 API 调用传递并相应地显示数据。

这很好用,当我切换选项卡时,我正在获取数据,但是当我尝试从数据表中搜索然后单击另一个选项卡时,我收到错误为-

无法对未安装的组件执行 React 状态更新。这是一个空操作,但它表明您的应用程序中存在内存泄漏。要修复,请取消 componentWillUnmount 方法中的所有订阅和异步任务。

下面是我的示例代码:

组件.jsx

import React, { Component } from "react";
import axios from "axios";

class Details extends Component {
  constructor() {
    super();
    this.state = {
      data: [],
      flag: 0
    };

  }

  componentDidMount() {
    const params = new FormData();
    params.append("status", "upcoming");
    axios.post("details/", params).then(res => {

      if (res.data.result === 1) {
        this.setState({ data: res.data.data, flag: 1 });
      }
    });
  }



  handleClick = event => {
    const params = new FormData();
    params.append("status", event.target.getAttribute("data-value"));
    axios.post("details/", params).then(res => {
      if (res.data.result === 1) {
        this.setState({ data: res.data.data, flag: 1 });
      }
    });
  };

  render() {
    return (
      <div className="col-md-9 col-sm-9 col-xs-12">
        <div className="right_panel">

          <h2>Listing</h2>

          <div className="responsive-tabs text-center ">
            <ul className="nav nav-tabs" role="tablist">
              <li role="presentation" className="active">
                <a
                  href="#Upcoming"
                  data-value="upcoming"
                  onClick={this.handleClick}
                  aria-controls="Upcoming"
                  role="tab"
                  data-toggle="tab"
                >
                  Upcoming
                </a>
              </li>
              <li role="presentation" className="">
                <a
                  href="#Current"
                  data-value="active"
                  onClick={this.handleClick}
                  aria-controls="Current"
                  role="tab"
                  data-toggle="tab"
                >
                  Current
                </a>
              </li>
              <li role="presentation" className="">
                <a
                  href="#past"
                  data-value="past"
                  onClick={this.handleClick}
                  aria-controls="past"
                  role="tab"
                  data-toggle="tab"
                >
                  Past
                </a>
              </li>
            </ul>
            <div
              id="tabs-content"
              className="tab-content panel-group table-responsive"
            >
              <div className="panel-heading" role="tab" id="heading2">
                <a
                  href="#Upcoming"
                  className="text-left collapsed textuppercase"
                  role="button"
                  data-toggle="collapse"
                  data-parent="tabs-content"
                  aria-expanded="true"
                  aria-controls="Upcoming"
                >
                  <i className="fas fa-list-ul" /> Upcoming
                  <i className="fas fa-chevron-down pull-right" />
                </a>
              </div>
              <div
                id="Upcoming"
                role="tabpanel"
                className="tab-pane active panel-collapse collapse in"
                aria-labelledby="heading2"
              >
                <table
                  id="first_Datatable"
                  className="display"
                  style={{ width: "100%" }}
                >
                  <thead>
                    <tr>
                      <th>#</th>
                      <th>Name</th>
                      <th>Open</th>
                      <th>Close</th>
                      <th>Listed</th>
                      <th>Price</th>
                      <th>Size</th>
                    </tr>
                  </thead>
                  {this.state.flag === 1 ? (
                    <tbody>
                      {this.state.data.map(d => (
                        <tr key={d.ipo_details_id}>
                          <td className="text-center">{d.ipo_details_id}</td>
                          <td>
                            <a href="#" title="">
                              {d.name}
                            </a>
                          </td>
                          <td>{d.open_date}</td>
                          <td>{d.close_date}</td>
                          <td>{d.size}</td>
                          <td>{d.listing}</td>
                          <td>{d.price}</td>
                        </tr>
                      ))}
                    </tbody>
                  ) : null}
                </table>
              </div>

              <div className="panel-heading" role="tab" id="heading3">
                <a
                  href="#Current"
                  className="collapsed text-left textuppercase"
                  role="button"
                  data-toggle="collapse"
                  data-parent="tabs-content"
                  aria-expanded="true"
                  aria-controls="Current"
                >
                  <i className="fas fa-list-ul" /> Current{" "}
                  <i className="fas fa-chevron-down pull-right" />
                </a>
              </div>

              <div
                id="Current"
                role="tabpanel"
                className="tab-pane panel-collapse collapse"
                aria-labelledby="heading3"
              >
                <table
                  id="second_Datatable"
                  className="display"
                  style={{ width: "100%" }}
                >
                  <thead>
                    <tr>
                      <th>#</th>
                      <th>Name</th>
                      <th>Open</th>
                      <th>Close</th>
                      <th>Listed</th>
                      <th>Price</th>
                      <th>Size</th>
                    </tr>
                  </thead>
                  {this.state.flag === 1 ? (
                    <tbody>
                      {this.state.data.map(d => (
                        <tr key={d.ipo_details_id}>
                          <td className="text-center">{d.ipo_details_id}</td>
                          <td>
                            <a href="#" title="">
                              {d.name}
                            </a>
                          </td>
                          <td>{d.open_date}</td>
                          <td>{d.close_date}</td>
                          <td>{d.size}</td>
                          <td>{d.listing}</td>
                          <td>{d.price}</td>
                        </tr>
                      ))}
                    </tbody>
                  ) : null}
                </table>
              </div>

              <div className="panel-heading" role="tab" id="heading3">
                <a
                  href="#past"
                  className="collapsed text-left textuppercase"
                  role="button"
                  data-toggle="collapse"
                  data-parent="tabs-content"
                  aria-expanded="true"
                  aria-controls="past"
                >
                  {" "}
                  <i className="fas fa-list-ul" /> Past{" "}
                  <i className="fas fa-chevron-down pull-right" />
                </a>
              </div>

              <div
                id="past"
                role="tabpanel"
                className="tab-pane panel-collapse collapse"
                aria-labelledby="heading3"
              >
                <table
                  id="third_Datatable"
                  className="display"
                  style={{ width: "100%" }}
                >
                  <thead>
                    <tr>
                      <th>#</th>
                      <th>Name</th>
                      <th>Open</th>
                      <th>Close</th>
                      <th>Listed</th>
                      <th>Price</th>
                      <th>Size</th>
                    </tr>
                  </thead>
                  {this.state.flag === 1 ? (
                    <tbody>
                      {this.state.data.map(d => (
                        <tr key={d.ipo_details_id}>
                          <td className="text-center">{d.ipo_details_id}</td>
                          <td>
                            <a href="#" title="">
                              {d.name}
                            </a>
                          </td>
                          <td>{d.open_date}</td>
                          <td>{d.close_date}</td>
                          <td>{d.size}</td>
                          <td>{d.listing}</td>
                          <td>{d.price}</td>
                        </tr>
                      ))}
                    </tbody>
                  ) : null}
                </table>
              </div>
            </div>
          </div>
        </div>
      </div>
    );
  }
}

export default Details;

我尝试使用 componentWillUnmount 进行更新,但没有解决。

我在 index.html 中初始化数据表。

那么可能的解决方案是什么。

4

2 回答 2

1

看起来这里的问题是您有一个以组件状态存储的数据模型,但该组件并没有持续很长时间。所以你有几个选择:

  • 保持组件中的状态,并在组件卸载时取消异步请求。这可以在 axios 中使用取消标记来完成,您将在构造时创建并在卸载时触发。这也将取消 http 请求,因此另一端的服务器不必响应它。如果在切换选项卡时暂停任何正在进行的请求是您想要的行为,这可能是最干净的选项。
  • 只是忽略警告。这取决于您,是否解决此问题很重要。它似乎不会影响行为。摩根的回答有效地做到了这一点,这是一个完全可行的解决方案,但它确实违背了警告的目的
  • 将状态移出组件(并将其作为道具或上下文传递)。如果状态没有存储在组件中,那么在组件卸载后更新它不再是问题。附带的好处是,如果您不想,每次挂载组件时都不必重新获取状态。您可以将状态保留在不会卸载的更高级别的父组件中,并将更新处理程序以及状态传递给该组件,或者您可以使用ReduxMobX 之类的东西来为您处理状态。
  • 切换选项卡时不要卸载组件。如果您保持组件呈现,但只是用 html 和 css 隐藏它,那么组件将保持挂载。您还可以执行其他花哨的技巧,例如保持组件已安装但在“屏幕外”文档片段中。这样做的好处是可以加快渲染速度,但可以使用更多的内存,也是一种反抗模式。

您选择哪个选项取决于您想要完成的任务。

于 2018-12-29T01:58:05.797 回答
0

似乎问题源于您在 componentDidMount 中发送的 POST 请求。

  componentDidMount() {
    const params = new FormData();
    params.append("status", "upcoming");
    axios.post("details/", params).then(res => {

      if (res.data.result === 1) {
        this.setState({ data: res.data.data, flag: 1 });
      }
    });
  }

如果你if用这样的东西修改你的状态更新之前的语句怎么办?

if (res.data.result === 1 && this.state) {

这样它只会尝试更新状态(如果this.state存在)?足够简单和优雅。

如果这不起作用,请告诉我!

于 2018-12-29T00:46:29.093 回答