reactjs - 有人有这个问题吗?“修复,取消componentWillUnmount方法中的所有订阅和异步任务”
问题描述
我在实现反应应用程序时遇到以下消息。有没有人有同样的问题?
警告:无法对未安装的组件执行 React 状态更新。这是一个空操作,但它表明您的应用程序中存在内存泄漏。要修复,请取消 componentWillUnmount 方法中的所有订阅和异步任务。在 ProductList 中(在 App.js:44)
我的入口页面是 ProductList 组件。加载入口页面后,如果我单击标题中的 LogOut,我会遇到该消息。有人对此有什么建议吗?
所以我提到了几个答案,比如
无法在未安装的组件上调用 setState(或 forceUpdate)。这是一个无操作,但它表明您的应用程序中存在内存泄漏
但是我无法解决它,为什么会发生这种情况。:(
应用程序.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;
产品列表.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;
如果您提供一些建议,那将是很大的帮助。
解决方案
问题在内部componentDidUpdate
,因为this.setState
是异步操作,所以会出现错误。
它是如何发生的?
- 发生注销操作
- ProductList
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
}
}
推荐阅读
- python - Python - 删除以相反顺序排列的重复列表
- php - Laravel jwt 在组外使用中间件
- java - 在 JavaFX 中闪烁一个矩形
- sql - 重命名sql server中现有表中的列,其中列名为空
- apache-spark - 对远程火花大师执行“火花提交”很热吗?
- typescript - Vue.set - TypeScript 推断的错误类型
- android - 测试传感器正常工作的常用方法有哪些
- google-analytics - GoogleAnalytics API:有没有办法通过特定的会话 id 获取数据?
- javascript - 如何使用 jquery 或 javascript 选择第一个收音机作为默认值
- java - 使用 Java 的 gRPC 中的 OAuth