与Tabs一起使用时,ReactJS无法更新状态 [英] ReactJS could not update state when used with Tabs

查看:74
本文介绍了与Tabs一起使用时,ReactJS无法更新状态的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a react component with 3 tabs, and each tab contains a datatable which will be populated with the API call result on the basis of active tab. So everytime there will be a parameter which I pass with API call and display data accordingly.

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

This is working great, I am getting data when I switch through tabs, but when I try to search from the datatable and then click on another tab I get the error as-

无法在已卸载的组件上执行React状态更新.这是 无操作,但这表示您的应用程序中发生内存泄漏.修理, 取消所有订阅和异步任务 componentWillUnmount方法.

Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method.

下面是我的示例代码:

component.jsx

component.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更新,但没有解决.

I tried updating with componentWillUnmount, but didn't solved.

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

I am initializing datatable in index.html.

那么这可能是什么解决方案.

So what could be the possible solution for this.

推荐答案

这里的问题似乎是您有一个数据模型,该数据模型存储在组件状态下,但是该组件不会停留很长时间.因此,您有几种选择:

It looks like the problem here is that you have a data model which is getting stored in component state, but that component isn't sticking around very long. So you have several options:

  • 保留组件中的状态,并在卸载组件时取消异步请求.这可以使用取消令牌在axios中完成,您可以在构造时创建并在卸载时触发.这也会取消http请求,因此另一端的服务器不必响应它.如果您要的是在切换选项卡时暂停正在进行的任何请求,那么这可能是最干净的选择.
  • 只需忽略警告.如果要解决此问题很重要,则取决于您.它似乎并没有影响行为. Morgan的答案有效地做到了这一点,这是一个完全可行的解决方案,但确实击败了 MobX 为您处理状态.
  • 切换选项卡时请勿卸载组件.如果保持组件呈示状态,而只是用html和css隐藏它,则该组件将保持挂载状态.您还可以执行其他一些花哨的技巧,例如保持组件安装在屏幕外"文档片段中.这样做的好处是它可以加快渲染速度,但是可以使用更多的内存,并且还是一种反模式.
  • Keep the state in the component, and cancel the async request when the component unmounts. this can be done in axios using cancel tokens, which you would create on construction and trigger on unmount. This would also cancel the http request, so the server on the other side wouldn't have to respond to it. This might be the cleanest option, if halting any requests in progress when tabs are switched is the behavior you want.
  • Just ignore the warning. That's up to you, if it is important to fix this or not. It doesn't seem to effect behavior. Morgan's answer effectively does this, and it's a perfectly viable solution, but it does defeat the purpose of the warning.
  • Move the state out of the component (and pass it in as props or context). If the state is not stored in the component, then updating it after the component is unmounted is no longer a problem. As a side benefit, you don't have to re-fetch the state every time you mount the component, if you don't want to. You can keep the state in a higher level parent component that doesn't unmount and pass an update handler as well as the state to this component, or you can use something like Redux or MobX to handle state for you.
  • Don't unmount the component when switching tabs. If you keep the component rendered, but just hide it with html and css, then the component will stay mounted. There are also other fancy tricks you can do such as keeping the component mounted but in an "offscreen" document fragment. The benefits of this is that it can speed up rendering, but it can use more memory, and is also kind of a react anti pattern.

选择哪种选项取决于您要完成的工作.

Which option you choose depends on what you want to accomplish.

这篇关于与Tabs一起使用时,ReactJS无法更新状态的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆