React-Native AsyncStorage:我检索一个数组,但它只是数组的一个对象
我使用 AsyncStorage 来存储和检索对象数组。数组的结构如下:
const tracks = [
{
title: title1,
exercises: [
{
object1Info...
},
{
object2Info...
}
]
},
{
title: title2,
exercises: [
{
object1Info...
}
]
},
{
title: title3,
exercises: [
{
object1Info...
}
]
}
]
如您所见,数组中的对象本身包含数组,数组又包含对象。
我像这样存储数组:
const storeData = async (array) => {
try {
const stringifiedArray = JSON.stringify(array)
await AsyncStorage.setItem('@tracks_array', stringifiedArray)
} catch (e) {
console.log("Error saving data")
}
}
这似乎工作正常。然后我像这样检索数据:
const retrieveData = async () => {
try {
const jsonValue = await AsyncStorage.getItem('@tracks_array');
console.log('Parsed value: ' + JSON.parse(jsonValue)); //This prints 'Parsed value: [object Object],[object Object],[object Object],[object Object]'
return jsonValue !== null ? JSON.parse(jsonValue) : null;
} catch (e) {
console.log("Error retrieving data")
}
}
这似乎也工作正常。 我也将该数组存储为状态。所以我想要做的是将一个对象添加到状态中的数组,将该新数组存储在 AsyncStorage 中,然后检索该数组并将这个新数组设置回状态。存储对象似乎没有问题。
当我检索新数组时,
console.log(JSON.parse(jsonValue))
在
retrieveData
内,它会打印
[object Object],[object Object],[object Object],[object Object]
。但是,在我调用
const newData = withdrawData()
后,
console.log(newData)
只打印
[object Object]
。这是我第一次使用 AsyncStorage,所以我一定是误解了什么。为什么它只返回一个对象,而不是整个数组?
编辑:共享整个组件代码:
import {
StyleSheet,
ScrollView,
View,
Text
} from 'react-native';
import Modal from 'react-native-modal';
import AsyncStorage from '@react-native-community/async-storage'
import Track from './Track.js';
import New from './New.js';
class Main extends Component {
constructor(props) {
super(props);
this.state = {
tracksData: tracks,
newTrack: false,
newExercise: false
}
storeData(this.state.tracksData);
}
renderTracks(data) {
console.log('Main data = ' + data)
return data.map((item, i) => {
console.log('Item = ' + item)
return (
<Track key={i} data={item} />
)
});
}
render() {
return (
<ScrollView horizontal={true} style={styles.Main}>
{this.renderTracks(this.state.tracksData)}
<Track data={{title: 'NewTrack', exercises: 'NewTrack'}} newTrackBox={this.toggleTrackBox} />
<Modal isVisible={this.state.newTrack} coverScreen={true}>
<New type={'track'} visible={this.toggleTrackBox} add={(name) => this.addTrack(name)}/>
</Modal>
</ScrollView>
);
}
toggleTrackBox = () => {
this.setState({
newTrack: !this.state.newTrack
})
}
addTrack = (name) => {
this.setState({
newTrack: false
});
var newTracks = this.state.tracksData;
newTracks.push({title: name, exercises: []})
console.log('newTracks = ' + newTracks)
storeData(newTracks);
this.updateData();
}
updateData() {
var newData = retrieveData();
console.log('newData = ' + newData)
setTimeout(() => {
console.log('Retrieved data = ' + newData);
if (newData) {
this.setState({
tracksData: newData
});
console.log("Data updated");
return true;
} else {
console.log("Data couldn't be retrieved");
return false;
}
}, 5000)
}
}
const storeData = async (value) => {
try {
const stringifiedArray = JSON.stringify(value)
console.log('Value to store: ' + value)
console.log('Stringified value to store: ' + stringifiedArray)
await AsyncStorage.setItem('@tracks_array', stringifiedArray)
//alert("Success saving data!")
} catch (e) {
console.log("Error saving data")
alert("Error saving data");
}
}
const retrieveData = async () => {
try {
const jsonValue = await AsyncStorage.getItem('@tracks_array');
console.log('Stringified value retrieved: ' + jsonValue)
console.log('Parsed value: ' + JSON.parse(jsonValue))
return jsonValue !== null ? JSON.parse(jsonValue) : null;
} catch (e) {
console.log("Error retrieving data")
alert("Error retrieving data");
}
}
const tracks = [ //each member of this array is sent to a Track
{
title: 'Pull-up', // used in Track
exercises: [ // each member of this array is sent to an Exercise by Track
{
name: 'Pull-up', // used in Exercise
setStart: 2, // this and below used to calculate no of tiles and their contents, which are then sent to Tile
setEnd: 3,
repStart: 5,
repEnd: 8,
isInSeconds: false,
inProgress: null,
completed: true
},
{
name: 'Weighted Pull-up',
setStart: 3,
setEnd: 3,
repStart: 5,
repEnd: 8,
isInSeconds: false,
inProgress: [3, 5],
completed: false
}
]
},
{
title: 'Dip',
exercises: [
{
name: 'Dip',
setStart: 2,
setEnd: 3,
repStart: 5,
repEnd: 8,
isInSeconds: false,
inProgress: null,
completed: true
}
]
},
{
title: 'Squat',
exercises: [
{
name: 'Pistol squat',
setStart: 2,
setEnd: 3,
repStart: 5,
repEnd: 8,
isInSeconds: false,
inProgress: [2, 8],
completed: false
}
]
}
]
const styles = StyleSheet.create({
Main: {
flex: 1,
flexDirection: 'row',
backgroundColor: '#022763'
}
})
export default Main;
另外,我应该提到,我收到的实际错误是:
TypeError:undefined 不是一个函数(靠近'...data.map...')
“retrieveData”是异步函数,因此返回一个 Promise。
发生的事情是它没有完成检索数据,因此 newData 从所有数组中获取了 1 个对象。
尝试像这样更改 updateData:
updateData() {
var newData = retrieveData().then(data => {
console.log('newData = ' + newData)
setTimeout(() => {
console.log('Retrieved data = ' + newData);
if (newData) {
this.setState({
tracksData: newData
});
console.log("Data updated");
return true;
} else {
console.log("Data couldn't be retrieved");
return false;
}
}, 5000)
};
}
我已经解决了这个问题。我使用 AsyncStorage 检索数据,然后将该数据设置为如下状态:
var newData = asyncRetrieveDataFunction();
this.setState({state1: newData})
但是,由于我将
retrieveData()
函数声明为异步,因此它在数据检索完成之前设置了状态。解决方案是使用
then
关键字并将其更改为如下内容:
asyncRetrieveDataFunction().then(data => this.setState({state1: data}));
这可确保在将数据分配给状态之前已返回数据。