【发布时间】:2018-12-01 20:23:39
【问题描述】:
我在实现 React 应用程序时遇到以下消息。有没有人有同样的问题?
警告:无法对未安装的组件执行 React 状态更新。这是一个空操作,但它表明您的应用程序中存在内存泄漏。要解决此问题,请取消 componentWillUnmount 方法中的所有订阅和异步任务。在 ProductList 中(在 App.js:44)
我的入口页面是 ProductList 组件。加载入口页面后,如果我单击标题中的 LogOut,我会遇到该消息。有人对此有什么建议吗?
所以我提到了几个答案,比如
但是我无法解决它,为什么会发生这种情况。 :(
App.js
import React, { Component } from "react";
import { Route } from "react-router-dom";
import Header from "./Header";
import ProductList from "./ProductList";
import Login from "./Login";
import Logout from "./Logout";
import "./App.css";
class App extends Component {
constructor() {
super();
this.state = {
query: "",
isLoggedIn: false
};
this.handleLoginStatus = this.handleLoginStatus.bind(this);
this.handleLogoutStatus = this.handleLogoutStatus.bind(this);
this.setSearchKeyword = this.setSearchKeyword.bind(this);
}
handleLoginStatus() {
this.setState({ isLoggedIn: true });
}
handleLogoutStatus() {
this.setState({ isLoggedIn: false });
}
setSearchKeyword(query) {
this.setState({
query: query
});
}
render() {
return (
<div>
<Header setSearchKeyword={this.setSearchKeyword} />
<Route
path="/"
exact={true}
render={() => (
<ProductList
query={this.state.query}
isLoggedIn={this.state.isLoggedIn}
/>
)}
/>
<Route
path="/login"
render={() => (
<Login
isLoggedIn={this.state.isLoggedIn}
handleLoginStatus={this.handleLoginStatus}
/>
)}
/>
<Route
path="/logout"
render={() => (
<Logout
isLoggedIn={this.state.isLoggedIn}
handleLogoutStatus={this.handleLogoutStatus}
/>
)}
/>
</div>
);
}
}
export default App;
ProductList.js
import React, { PureComponent } from "react";
import { Table } from "react-bootstrap";
import axios from "axios";
class ProductList extends PureComponent {
constructor(props) {
super(props);
this.state = {
products: null,
loaded: false
};
}
// componentWillReceiveProps(nextProps) {
// console.log(nextProps.query);
// }
componentDidUpdate() {
const url =
"https://localhost/product/search?query=" + this.props.query;
const options = {
method: "GET",
headers: {
Authorization: "Bearer " + localStorage.getItem("auth-token")
},
url
};
axios(options)
.then(response => {
let products = response.data;
this.setState({ products: products });
})
.catch(error => {
console.log("axios error", error);
});
}
componentDidMount() {
const url =
"https://localhost/product/search?query=" + this.props.query;
const options = {
method: "GET",
headers: {
Authorization: "Bearer " + localStorage.getItem("auth-token")
},
url
};
axios(options)
.then(response => {
let products = response.data;
this.setState({ products: products, loaded: true });
})
.catch(error => {
console.log("axios error", error);
});
}
// ComponentWillUnmount() {
// this.isUnmounted = true;
// }
render() {
if (this.state.loaded) {
let columnNames = ["Num", "Name", "Indications", "features"];
let fieldNames = ["num", "name", "indications", "features"];
var tableHeaders = (
<tr>
{columnNames.map(column => {
return <th key={column}>{column}</th>;
})}
</tr>
);
var tableBody = this.state.products.map((product, i) => {
return (
<tr key={product + "_" + i}>
{fieldNames.map((field, j) => {
if (j === 0) {
return <td key={product.name + "_" + i + "_" + j}>{i + 1}</td>;
} else {
return (
<td key={product.name + "_" + i + "_" + j}>{product[field]}</td>
);
}
})}
</tr>
);
});
}
return (
<div>
<Table striped bordered condensed hover>
<thead>{tableHeaders}</thead>
<tbody>{tableBody}</tbody>
</Table>
</div>
);
}
}
export default ProductList;
如果你能给点建议,那将是很大的帮助。
【问题讨论】:
-
您的
<Route/>组件处理组件的安装和卸载以及当您尝试注销时(意味着强制<Route/>组件卸载<ProductList />或任何会导致调用 componentWillUnmount 的组件)你的axios通话被打断,你得到了上述结果。要解决此问题,您应该完全按照警告消息所说的去做:cancel all subscriptions and asynchronous tasks in the componentWillUnmount method -
这个(虽然有点老)也有关系:reactjs.org/blog/2015/12/16/ismounted-antipattern.html.
-
非常感谢您的回答。我会仔细阅读。