Reputation: 99
I'm fetching data in my local database (sqlite) and updating the state, and this error is appearing:
Can't perform a React state update on an unmounted component. This is a >no-op, but it indicates a memory leak in your application. To fix, >cancel all subscriptions and asynchronous tasks in the >componentWillUnmount method.
no solution helped me.
_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>
}
}
Upvotes: 3
Views: 26466
Reputation: 77
Whenever there is any task running and you pull off your screen by navigating back,
this warning appears,
You do not need to worry about anything.
This is normal warning.
Let say you have done setState
it is running and you unmount everything.
So here system gonna think that I'm doing setState
but i do not have class, this, or/and variable to do it.
SO it just gives you warning that everything is unmounted and I can't do it on unmounted component.
And about killing asynchronous task...,
Let say you have set a timer of 1 minute and every 1 minute you are doing setState
on on state variable.
let this.timerState = setTimeout(() => {
this.setState({ timer: this.state.timer + 1 });
}, 1000);
Now no matter what you do this one minute timer will run infinite time until you kill your application.
So system is suggesting you to kill this type of task when component is unmounting.
So do clearTimeout(this.timerState)
on life cycle method componentWillunmount
.
So don't bother about warning there is nothing that can be leaked.
Upvotes: 7
Reputation: 1055
Initialize db in constructor and add it to state as follow:
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,
};
}
Then getYears on componentDidMount as follow:
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();
}
Simply Close the connection on componentWillUnMount as follow:
componentWillUnmount() {
const { db } = this.state;
db.close();
}
I hope it help you.
Upvotes: 0