在实施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;
如果您提供一些建议,那将是很大的帮助。
答案 0 :(得分:4)
问题出在componentDidUpdate
内部,并且由于this.setState
是异步操作,因此出现错误。
它是怎么发生的?
componentDidUpdate
不受任何条件的保护,this.setState
被无限调用。componentWillUnmount
触发器this.setState({ products: products })
中的异步componentDidUpdate
操作尝试更新状态要解决您的问题,请在componentDidUpdate
内添加一个条件。
您可以在componentDidUpdate()中立即调用setState(),但请注意 必须将其包装在上面示例中所示的条件下,或者 您将导致无限循环。这也会造成额外的 重新渲染虽然对用户不可见,但可能会影响 组件性能。如果您尝试将某些状态“镜像”到 道具来自上方,请考虑直接使用道具。读 有关为何将道具复制到状态会导致错误的更多信息。
示例解决方案:
componentDidUpdate(prevProps) {
// Please do not forget to compare props
if (this.props.somethingChanged !== prevProps.somethingChanged) {
// this.setState logic here
}
}