[英]React Warning: Can't perform a React state update on an unmounted component. To fix, cancel all subscriptions
[英]How to fix “Can't perform a React state update on an unmounted component.” error in React Native
我在本地數據庫(sqlite)中獲取數據並更新狀態,並且出現此錯誤:
無法在已卸載的組件上執行React狀態更新。 這是> no-op,但表示您的應用程序中發生內存泄漏。 要修復,請> componentWillUnmount方法取消所有預訂和異步任務。
沒有解決方案對我有幫助。
_isMounted = false;
constructor(props) {
super(props);
this.state = {
slug: "",
value: "",
cod_year: "",
months: [],
years: [],
loadingData: true,
};
}
db = openDatabase({ name: 'test.db', createFromLocation : '~my_finances.db'});
getYears = () => {
if(this.state.loadingData){
this.db.transaction((txn)=>{
txn.executeSql(
"SELECT cod, slug FROM year",
[],
(tx, res) => {
if(res.rows.length > 0){
rows = [];
for(let i=0; i<res.rows.length;i++){
rows.push(res.rows.item(i));
}
this.setState({years: rows}, {loadingData: false});
}
}
)
})
}
}
componentDidMount(){
this._isMounted = true;
this.getYears();
}
render() {
const state = this.state;
if(!state.loadingData){
const pickerItens = state.years.map((record, index) => {
<Picker.Item label={record.slug} value={record.cod}/>
})
return (
<View style={{flex: 1}} >
<ScrollView style={styles.container}>
<View style={styles.form_add}>
<Text style={styles.form_slug} > Adicionar </Text>
<TextInput
placeholder="Digite o mês..."
onChangeText={(slug) => { this.setState({slug}) }}
value={this.state.slug}
style={styles.input_add}
/>
<TextInput
placeholder="Digite o valor..."
onChangeText={(value) => { this.setState({value}) }}
value={this.state.value}
style={styles.input_add}
/>
<Picker onValueChange = {(cod_year) => {this.setState({cod_year})}}>
{ pickerItens }
</Picker>
<Button color="#7159C1" title="Salvar" onPress={() => this.addYear()} />
</View>
</ScrollView>
<Footer navigate={this.props.navigation.navigate} />
</View>
);
}else{
<Text> Loading... </Text>
}
}
每當有任何任務在運行時,您通過向后導航來拉開屏幕,
出現此警告,
您無需擔心任何事情。
這是正常警告。
假設您已完成setState
的運行,然后卸載了所有內容。 因此,這里系統會認為我正在執行setState
但是我沒有類,此或/和變量來執行此操作。
因此,它只是警告您所有內容均已卸載,而我無法在已卸載的組件上執行此操作。
關於殺死異步任務...,
假設您將計時器設置為1分鍾,並且每1分鍾對狀態變量進行一次setState
設置。
let this.timerState = setTimeout(() => {
this.setState({ timer: this.state.timer + 1 });
}, 1000);
現在,無論您做什么,這一分鍾的計時器將無限期運行,直到您終止應用程序。
因此,系統建議您在卸載組件時取消此類任務。
因此,對生命周期方法componentWillunmount
進行clearTimeout(this.timerState)
。
因此,不要擔心警告沒有泄漏的內容。
在構造函數中初始化db並將其添加到state,如下所示:
constructor(props: Props) {
super(props);
const db = SQLite.openDatabase({
name: 'test.db',
location: 'default',
createFromLocation: '~my_finances.db',
},
() => {},
error => {
console.log(error);
}
);
this.state = {
db,
slug: "",
value: "",
cod_year: "",
months: [],
years: [],
loadingData: true,
};
}
然后在componentDidMount上進行getYears,如下所示:
getYears = () => {
const { loadinData, db } = this.state
if(loadingData){
db.transaction((txn) => {
txn.executeSql(
"SELECT cod, slug FROM year",
[],
(tx, res) => {
if(res.rows.length > 0){
let rows = [];
for(let i=0; i<res.rows.length;i++){
rows.push(res.rows.item(i));
}
this.setState({years: rows, loadingData: false});
}
})
})
}
}
componentDidMount() {
this.getYears();
}
只需按以下步驟關閉componentWillUnMount上的連接即可:
componentWillUnmount() {
const { db } = this.state;
db.close();
}
希望對您有幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.