Reputation: 3709
I have saved one data inside one class of my react-native project. With saving data I start a new screen. In that screen I am retrieving that saved data. For that purpose, I call AsyncStorage.getItem('token') function inside the render function.
Here is the code for that class-
import React from 'react';
import { StyleSheet, Text, View, Image, AsyncStorage } from 'react-native';
import {Icon, Button, Container, Header, Content, Left} from 'native-base';
import CustomHeader from './CustomHeader';
class NoteMeHome extends React.Component {
state = {
text:'',
storedValue:'',
getValue: ''
};
static navigationOptions = ({navigation}) => ({
title: "Home",
headerLeft: <Icon name="ios-menu" style={{paddingLeft:10}}
onPress={()=>navigation.navigate('DrawerOpen')}/>,
drawerIcon:
<Image source={require('../assets/icon.png')}
style={styles.icon}
/>
})
render() {
const {storedValue} = this.state;
AsyncStorage.getItem('token').then(value =>
//AsyncStorage returns a promise so adding a callback to get the value
this.setState({ getValue: value })
//Setting the value in Text
);
return(
<Container>
<CustomHeader
title="Home"
drawerOpen={()=>this.props.navigation.navigate('DrawerOpen')}
/>
<Content contentContainerStyle={{flex:1, alignItems:'center',
justifyContent:'center', padding:10}}>
<Button full onPress={()=> this.props.navigation.navigate('Settings')}>
<Text style={{color:'white'}}>{storedValue}</Text>
</Button>
<Text>{this.state.getValue}</Text>
</Content>
</Container>
)
}
}
const styles = StyleSheet.create({
icon:{
height: 24,
width: 24
}
})
export default NoteMeHome;
After that, while running the project, in the above mentioned class, when I click any of my drawer items to go to another screen, it shows the following error in the console-
wanrning: can't call setState(or forceUpdate) on an unmounted component. This is no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asyncshronous tasks in the componentWillUnmount method.
I guess something goes wrong with AsyncStorage.getItem('token') function calling because if I remove the function it doesn't show any warning.
So, it would be very nice if someone helps me to know where should I call the following code-
AsyncStorage.getItem('token').then(value =>
//AsyncStorage returns a promise so adding a callback to get the value
this.setState({ getValue: value })
//Setting the value in Text
);
to remove the warning ?
Upvotes: 2
Views: 2810
Reputation: 3131
In react component render()
should always remain pure. One should never set state in render function, it a very bad pracice, in a simple component it might work fine. It only works because of the asynchronicity.
You should use componentDidMount
lifecycle method to fetch data from local storage.
componentDidMount() {
const token = await AsyncStorage.getItem('token');
this.setState({ getValue: token });
}
Upvotes: 0
Reputation: 340
Asif,
Here is what I had in mind :
import React from 'react';
import { StyleSheet, Text, View, Image, AsyncStorage } from 'react-native';
import {Icon, Button, Container, Header, Content, Left} from 'native-base';
import CustomHeader from './CustomHeader';
class NoteMeHome extends React.PureComponent {
state = {
text:'',
storedValue:'',
getValue: ''
};
static navigationOptions = ({navigation}) => ({
title: "Home",
headerLeft: <Icon name="ios-menu" style={{paddingLeft:10}}
onPress={()=>navigation.navigate('DrawerOpen')}/>,
drawerIcon:
<Image source={require('../assets/icon.png')}
style={styles.icon}
/>
});
componentDidMount() {
const token = await AsyncStorage.getItem('token');
this.setState({ getValue: token });
}
render() {
const {storedValue, getValue} = this.state;
return(
<Container>
<CustomHeader
title="Home"
drawerOpen={()=>this.props.navigation.navigate('DrawerOpen')}
/>
<Content contentContainerStyle={{flex:1, alignItems:'center',
justifyContent:'center', padding:10}}>
<Button full onPress={()=> this.props.navigation.navigate('Settings')}>
<Text style={{color:'white'}}>{storedValue}</Text>
</Button>
<Text>{getValue}</Text>
</Content>
</Container>
)
}
}
const styles = StyleSheet.create({
icon:{
height: 24,
width: 24
}
})
export default NoteMeHome;
I don't know if in your case you should actually try to handle the update of the component since you don't have any props.
Regards,
Upvotes: 1
Reputation: 1313
IMO you should use componentDidMount
for anything that you want to do in the beginning of a screen. To use AsyncStorage
remember that is an asynchronous
function so you have to wait for the function to complete so you can get the value.
For more information about react native's components please see this
For more information about 'waiting' for AsyncStorage using async
please see this examples
Upvotes: 0