I am newbie in ReactNative. ( I am very familiar with Raw Android)
Yesterday when I was using AsyncStorage ( incorrectly I think) , I met a problem that the View kept re-rendering every n millionseconds.
my code:
import React, { Component} from 'react';
import {Image, Platform, StyleSheet, Text, View, Button} from 'react-native'
import { AsyncStorage } from "react-native"
export default class StorageDemo extends Component{
constructor(props){
super(props)
AsyncStorage.setItem("visitTimes", 100)
this.state = {
isLoaded: false,
visitTimes: 0
}
}
readData = async () => {
try{
const result = await AsyncStorage.getItem("visitTimes")
this.setState(
{
visitTimes: result,
isLoaded: true
}
)
console.info("== loaded, this.state: ")
}catch(error){
console.error(error)
}
}
render() {
this.readData()
if(this.state.isLoaded){
return(
<View>
<Text>Loaded! </Text>
</View>
)
}else{
return(
<View>
<Text>Loading... </Text>
</View>
)
}
}
}
Also I opened a logcat window to check the log, I was shocked by the log: it kept re-rendering the View every 10 ms.
My environment:
code could be found here: https://github.com/sg552/react_native_lesson_demo/blob/master/screens/StorageDemo.js
I know my code is not correct (using async, await) , so my question is:
How to read from AsyncStorage and render it to page? How to correct my code?
thanks a lot!
Okay, so the problem is that you are calling your func this.readData()
inside the render, and that function itself is calling setState
which whenever is called, changes the state, which triggers a re-render on the component. So in this situation you have caused an infinite loop in the code, because setState
calls render, which in turn calls setState
again and you run out of memory.
To fix this quickly, you can remove the function call from your render, and add it to a button, so its only called when you want it to. Something like this:
import React, { Component} from 'react';
import {Image, Platform, StyleSheet, Text, View, Button} from 'react-native'
import { AsyncStorage } from "react-native"
export default class StorageDemo extends Component{
constructor(props){
super(props)
this.state = {
isLoaded: false,
visitTimes: 0
}
}
readData = async () => {
try{
const result = await AsyncStorage.getItem("visitTimes")
this.setState(
{
visitTimes: result,
isLoaded: true
}
)
console.info("== loaded, this.state: ")
}catch(error){
console.error(error)
}
}
render() {
if(this.state.isLoaded){
return(
<View>
<Text>Loaded! {this.state.visitTimes} </Text>
<Button
onPress={() => {
AsyncStorage.setItem("visitTimes", "100")
this.setState({isLoaded: false})
}}
title="Set Storage Item"
/>
</View>
)
}else{
return(
<View>
<Button
onPress={this.readData}
title="Load from async storage"></Button>
</View>
)
}
}
}
Try this and this should give you the value from localStorage!