gpt4 book ai didi

reactjs - 有人有这个问题吗? "To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method"

转载 作者:行者123 更新时间:2023-12-03 13:35:20 26 4
gpt4 key购买 nike

我在实现 React 应用程序时遇到以下消息。有人有同样的问题吗?

警告:无法对已卸载的组件执行 React 状态更新。这是一个空操作,但它表明应用程序中存在内存泄漏。要修复此问题,请在 componentWillUnmount 方法中取消所有订阅和异步任务。在 ProductList 中(位于 App.js:44)

我的入口页面是ProductList组件。加载入口页面后,如果我单击标题中的“注销”,我会遇到该消息。有人对此有什么建议吗?

所以我引用了几个答案,例如

Can't call setState (or forceUpdate) on an unmounted component. This is a no-op, but it indicates a memory leak in your application

但是我无法解决,为什么会发生这种情况。 :(

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;

产品列表.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 是异步操作,因此会显示错误。

这是怎么发生的?

  1. 发生注销操作
  2. ProductList componentDidUpdate 不受任何条件的保护,并且 this.setState 被无限调用。
  3. ProductList componentWillUnmount 触发器
  4. 来自 componentDidUpdate 的异步 this.setState({ products: products }) 操作尝试更新状态
  5. 出现错误

要解决您的问题,请在 componentDidUpdate 中添加一个条件。

官方文档about componentDidUpdate

You may call setState() immediately in componentDidUpdate() but note that it must be wrapped in a condition like in the example above, or you’ll cause an infinite loop. It would also cause an extra re-rendering which, while not visible to the user, can affect the component performance. If you’re trying to “mirror” some state to a prop coming from above, consider using the prop directly instead. Read more about why copying props into state causes bugs.

解决方案示例:

componentDidUpdate(prevProps) {
// Please do not forget to compare props
if (this.props.somethingChanged !== prevProps.somethingChanged) {
// this.setState logic here
}
}

关于reactjs - 有人有这个问题吗? "To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53574734/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com