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")
}
}

这似乎也很有效。我已经将数组存储为state。因此,我想做的是向处于状态的阵列添加一个对象,将新阵列存储在AsyncStorage中,然后检索该阵列并将该新阵列设置回状态。存储对象似乎没有问题。

当我检索到新数组和retrieveData中的console.log(JSON.parse(jsonValue))时,它会打印[object Object],[object Object],[object Object],[object Object]。然而,在我调用const newData = retrieveData()之后,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 is not a function (near '...data.map...')

"检索数据";是异步函数,因此返回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()函数声明为async,所以它是在数据检索完成之前设置状态的。解决方案是使用then关键字并将其更改为以下内容:

asyncRetrieveDataFunction().then(data => this.setState({state1: data}));

这样可以确保在将数据分配给状态之前已返回数据。

最新更新