简体   繁体   English

只能更新已安装或正在安装的组件。

[英]Can only update a mounted or mounting component.

Currently working on a personal project and i'm getting this error 目前正在处理个人项目,但出现此错误

Warning: Can only update a mounted or mounting component. This usually means you called setState, replaceState, or forceUpdate on an unmounted component. This is a no-op. Please check the code for the Graph component.

I also get the same issue for my App component. 我的App component.也遇到了同样的问题App component. I've done some reading on what the issue could be, but i'm non the wiser as to what the issue is with my code specifically. 我已经读了一些关于问题可能是什么的书,但是对于我的代码问题到底是什么,我并不明智。

Any insight would be greatly appreciated. 任何见识将不胜感激。

Here is a link to the running project (with sourcecode) on CodeSnadbox.io I've linked the offending code below as well. 这是CodeSnadbox.io上正在运行的项目(带有源代码)的链接,我也链接了下面的有问题的代码。

Here is the Graph Component 这是Graph Component

import React, { Component } from "react";
import { render } from "react-dom";
import { Line, Doughnut, Bar } from "react-chartjs-2";
import moment from "moment";
import PropTypes from "prop-types";

import styleConstants from "../misc/style_constants.js";

class Graph extends Component {
  constructor(props) {
    super(props);
    this.state = {
      label: "default",
      dataset: [],
      labels: []
    };
  }

  /**
   * https://min-api.cryptocompare.com/ for documentation
   */
  async getHistoryData(ticker = "BTC", currency = "USD", filter = "close") {
    try {
      let response = await fetch(
        `https://min-api.cryptocompare.com/data/histoday?fsym=${ticker}&tsym=${currency}&limit=60&aggregate=3&e=CCCAGG`
      );
      const responseJson = await response.json();
      const dataset = responseJson.Data.map(data => {
        return data[filter];
      });
      const labels = responseJson.Data.map(data => {
        return moment(new Date(data.time * 1000)).format("MMM Do YY");
      });

      this.setState({ dataset: dataset });
      this.setState({ labels: labels });
    } catch (error) {
      console.log(error);
    }
  }

  componentDidMount() {
    const { ticker, currency, filter } = this.props;
    this.getHistoryData(ticker, currency, filter);
  }

  render() {
    const { label, graphType } = this.props;
    const { dataset, labels } = this.state;

    const options = {
      legend: {
        fontColor: styleConstants.get("Dark")
      },
      scales: {
        yAxes: [
          {
            ticks: {
              fontColor: styleConstants.get("Light"),
              beginAtZero: true,
              callback: function(value, index, values) {
                if (parseInt(value) >= 1000) {
                  return (
                    "$" + value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")
                  );
                } else {
                  return "$" + value;
                }
              }
            }
          }
        ],
        xAxes: [
          {
            ticks: {
              fontColor: styleConstants.get("Light"),
              fontSize: 10,
              stepSize: 1,
              beginAtZero: true
            }
          }
        ]
      }
    };

    const data = {
      labels: labels,
      datasets: [
        {
          label: label,
          fill: true,
          lineTension: 0.1,
          backgroundColor: styleConstants.get("Medium"),
          borderColor: styleConstants.get("Medium"),
          borderCapStyle: "butt",
          borderDash: [],
          borderDashOffset: 0.0,
          borderJoinStyle: "miter",
          pointBorderColor: styleConstants.get("Light"),
          pointBackgroundColor: "#fff",
          pointBorderWidth: 1,
          pointHoverRadius: 5,
          pointHoverBackgroundColor: "rgba(75,192,192,1)",
          pointHoverBorderColor: "rgba(220,220,220,1)",
          pointHoverBorderWidth: 2,
          pointRadius: 1,
          pointHitRadius: 10,
          data: dataset
        }
      ]
    };
    return <Line data={data} options={options} />;
    // switch (graphType) {
    //   case "line":
    //     return <Line data={data} options={options} />;
    //     break;
    //   case "bar":
    //     return <Bar data={data} options={options} />;
    //     break;
    //   case "doughnut":
    //     return <Doughnut data={data} options={options} />;
    //     break;
    //   default:
    //     return null;
    // }
  }
}

Graph.propTypes = {
  label: PropTypes.string,
  graphType: PropTypes.string
};

Graph.defaultProps = {
  label: "Default String",
  graphType: "Default String"
};

export default Graph;

Here is the App Component also 这也是应用程序组件

import React, { Component } from "react";
import { render } from "react-dom";

import styled, { css } from "styled-components";

import styleConstants from "../misc/style_constants.js";

import Overview from "../components/Overview";
import Panel from "../components/Panel";
import Table from "../components/Table";

import Options from "./Options";
import Graph from "./Graph";

export default class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      selectedTicker: "BTC",
      currency: "USD",
      tickers: [],
      overview: []
    };
    this.updateTicker = this.updateTicker.bind(this);
    this.createGraph = this.createGraph.bind(this);
  }

  updateTicker(selectedValue) {
    const { value } = selectedValue;
    this.setState({ selectedTicker: value });
  }

  async getTickers() {
    try {
      const response = await fetch('https://api.coinmarketcap.com/v1/ticker/')
      const responseJSON = await response.json();
      this.setState({ tickers: responseJSON });
    } catch (error) {
      console.log("App getTickers() ", error);
    }
  }

  async getOverviewData() {
    try {
      const response = await fetch(`https://api.coinmarketcap.com/v1/global/?convert=${this.state.currency}`)
      const responseJSON = await response.json();
      this.setState({ overview: responseJSON });
    } catch (error) {
      console.log("App getOverviewData() ", error);
    }
  }

  componentDidMount() {
    this.getTickers();
    this.getOverviewData();
  }

  createGraph(ticker = "", currency = "", graphType = "", label = "", filter = "") {
    return (
      <Graph
        filter={filter}
        ticker={ticker}
        currency={currency}
        graphType={graphType}
        label={label}
      />
    )
  }

  render() {
    const { selectedTicker, currency } = this.state;
    const Container = styled.div`
      input:focus,
      select:focus,
      textarea:focus,
    `;

    const Title = styled.h1`
      text-align: center;
      color: ${styleConstants.get('Yellow')};
    `;

    const LightSpan = styled.span`
      font-weight: 200;
    `;

    return (
      <Container>
        <Title>
          Coin:<LightSpan>Dash</LightSpan>
        </Title>
        <Overview {...this.state.overview} />
        <Options
          selectedValue={this.state.selectedTicker}
          values={this.state.tickers.map(data => {
            return data.symbol;
          })}
          labels={
            this.state.tickers.map(data => {
              return data.id;
            })
          }
          updateTicker={this.updateTicker} />
        <Panel label={"Price Action"} content={this.createGraph(selectedTicker, currency, 'line', "Close", "close")} />
        <Panel label={"Highest Price"} content={this.createGraph(selectedTicker, currency, 'bar', "High", "high")} />
        <Panel label={"Lowest Price"} content={this.createGraph(selectedTicker, currency, 'bar', "Low", "low")} />
        <Panel label={"Top Ten List"} content={
          <Table header={["Rank", "Name", "Price", "Change(24 Hour)"]} collection={this.state.tickers} />

        } />

      </Container>
    );
  }
}

The problem is caused by stateless functional components that are defined inside the render method of App . 该问题是由在Apprender方法内定义的无状态功能组件引起的。 If you define the following functions outside of the App class, the error is fixed: 如果您在App类之外定义以下功能,则该错误已修复:

const Container = styled.div`
      input:focus,
      select:focus,
      textarea:focus,
    `;

const Title = styled.h1`
      text-align: center;
      color: ${styleConstants.get('Yellow')};
    `;

const LightSpan = styled.span`
      font-weight: 200;
    `;

export default class App extends Component {
..

The reason for the failure is that locally created SFC's change on each render, which causes them to unmount and remount, even though the rendering stays the same. 失败的原因是在每个渲染上本地创建的SFC的更改,即使渲染保持不变,也会导致它们的卸载和重新安装。 There are also some other local SFC's in the Table component, which did not create any warning, but do cause unnecessary remounting. Table组件中还有一些其他本地SFC,它们没有创建任何警告,但是会导致不必要的重新安装。

UPDATE: It was a bit of a puzzle, but the remaining warning came from one of the tests: 更新:这有点令人困惑,但是剩余的警告来自以下一项测试:

describe("App", () => {
  it("renders without crashing", () => {
    const div = document.createElement("div");
    ReactDOM.render(<App />, div);
    ReactDOM.unmountComponentAtNode(div);
  });
});

Which makes sense, as you unmount the component before the async action is completed. 这很有意义,因为您可以在异步操作完成之前卸载组件。

Here's a working sandbox: https://codesandbox.io/s/24o6vp4rzp (I've also removed the arrow function in content={..} , since that needs to be a value) 这是一个有效的沙箱: https : //codesandbox.io/s/24o6vp4rzp (我还删除了content={..}的箭头功能,因为这需要是一个值)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 只能更新已安装或正在安装的组件。 找不到错误 - Can only update a mounted or mounting component. findless error 只能更新已安装或安装的组件。 这通常意味着您在已卸载的组件上调用了setState() - Can only update a mounted or mounting component. This usually means you called setState() on an unmounted component setState(...):只能更新已安装或安装的组件。 这通常意味着您在已卸载的组件上调用了setState()。 这是一个无操作 - setState(…): Can only update a mounted or mounting component. This usually means you called setState() on an unmounted component. This is a no-op 警告:setState(…):只能更新已安装或正在安装的组件。 这通常意味着 - Warning: setState(…): Can only update a mounted or mounting component. This usually means setState只能更新已安装或安装的组件 - setState Can only update a mounted or mounting component 反应:只能更新已安装或正在安装的组件 - React: Can only update a mounted or mounting component setState(…):只能更新已安装或正在安装的组件 - setState(…): Can only update a mounted or mounting component 尝试在其他类中重用组件并获取错误:“警告:setState(...):只能更新已安装或安装的组件。 ” - Trying to re-use component in other class and getting error: “Warning: setState(…): Can only update a mounted or mounting > component. ” setState(…):即使已安装组件,也只能更新已安装或正在安装的组件 - setState(…): Can only update a mounted or mounting component even if component is mounted componentDidMount中的“只能更新已安装或正在安装的组件”警告 - “Can only update a mounted or mounting component ” warning in componentDidMount
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM