javascript - 我能找出这个错误的真正原因吗?(反应原生)
问题描述
首先我为我的英语道歉。我已经在 React to native 应用程序上工作了 4 个月。但有时我会收到此错误并且不介意。
警告:无法对未安装的组件执行 React 状态更新。这是一个空操作,但它表明您的应用程序中存在内存泄漏。要修复,请取消 %s.%s 中的所有订阅和异步任务,在 CustomerDetailScreen 中的 componentWillUnmount 方法(在 SceneView.tsx:123)
这是因为当我单击按钮时,我会打开一个屏幕,而当屏幕未完全加载时,我会按返回按钮。如何解决此警告?我将向您展示一些示例代码示例。
我希望我能解释一下。你能帮我解决这个话题吗?我想完全理解其中的逻辑。我在一些文章中读过一些名为 AbortController 的东西,但我并不确切知道。
constructor(props) {
super(props);
this._isMounted = false;
this.state = {
id: props.route.params.id,
username: '',
token: null,
cityId: 1,
townId: 1,
cityData: [],
townData: [],
selectedIndex: 0,
selectedCity: new IndexPath(0),
selectedTown: new IndexPath(0),
}
}
componentDidMount() {
this._isMounted = true;
this._isMounted && this._getToken();
}
componentWillUnmount() {
this._isMounted = false;
}
_getToken = async () => {
try {
const username = await AsyncStorage.getItem('username');
const token = await AsyncStorage.getItem('token');
if(token === null) {
await AsyncStorage.removeItem('token');
}else {
this.setState({ username: username, token: token });
this._isMounted && this.loadCustomerDetail();
}
} catch (error) {
console.log(error);
}
};
loadCustomerDetail() {
try {
const { username, token } = this.state;
if(token) {
const { id } = this.state;
var credentials = Base64.btoa(username + ':' + token);
var URL = `https://portal.xxxxxx.com/api/v1/Customer/${id}`;
axios.get(URL, {headers : { 'Espo-Authorization' : credentials }})
.then(this.dataSuccess.bind(this))
.catch(this.dataFail.bind(this));
}
}catch (err) {
console.log(err);
}
};
dataSuccess(response) {
this.setState({
isLoading: false,
cityId: response.data.cityId,
townId: response.data.townId
}, () => {
this.getCities();
});
}
getCities() {
const { username, token, cityId } = this.state;
let credentials = Base64.btoa(username + ':' + token);
axios.get('https://portal.xxxxx.com/api/v1/Cities', { headers : { 'Espo-Authorization' : credentials }})
.then((response) => {
response.data.list.sort(function(a, b) {
return Number(a.id) > Number(b.id);
});
this.setState({cityData: response.data.list}, () => {
this.setState({ selectedCity: new IndexPath(this.state.cityData[cityId-1].id - 1) });
this.getTowns(this.state.cityData[cityId-1].id);
});
}).catch((error) => {
console.log(error);
});
}
getTowns(cityId) {
this.setState({ townLoading: true });
const { username, token } = this.state;
let credentials = Base64.btoa(username + ':' + token);
axios.get(`https://portal.xxxxx.com/api/v1/Towns/action/TownList?cityId=${cityId}`, { headers : { 'Espo-Authorization' : credentials }})
.then((response) => {
this.setState({ townData: response.data, townLoading: false }, () => {
for (const [key, value] of Object.entries(this.state.townData)) {
if(value.id === this.state.townId) {
this.setState({ selectedTown: new IndexPath(key) })
}
}
});
}).catch((error) => {
console.log(error);
});
}
解决方案
示例区域:
this.setState({ username: username, token: token });
this._isMounted && this.loadCustomerDetail();
您可以看到setState
即使不再安装组件也会调用它。
使固定
确保在更改状态之前安装组件:
if (this._isMounted) {
this.setState({ username: username, token: token });
this.loadCustomerDetail();
}
推荐阅读
- java - 在 Apache Flink 中暂停数据流并查看算子的状态
- tornadofx - TornadoFX - 如何使用自定义单元工厂修复 ListView 在删除项目时无法正确更新?
- c# - 自动映射器扩展方法
- ios - URLSessions 或 AlamoFire 用于下载每天更新一次的网页?
- javascript - 根据父组件的状态改变子组件,无需重新渲染
- laravel - Laravel:抓取嵌套项目
- scala - 添加 RDD[String,Array[String,Int]] 的 Int 值
- javascript - HTML/js 如何从多个不同的图像宽度设置多个 div 宽度?
- time-complexity - 当您需要在每次插入后重新计算树上的平衡因子时,AVL 树插入 O(log n) 如何?
- angular - Angular 6 / Typescript - 如何检查变量中是否有单个数字