react-native - 如何使用 Asyncstorage 在第二个屏幕上保存和查看 JSON 数据?
问题描述
我有一些代码无法按预期工作,当我单击收藏图标时,它应该保存到异步存储。该代码用于从平面列表中选择电影,我遇到的问题是将其保存到 asyncStorage,然后当我单击页面以在平面列表中显示选定的喜爱电影时,什么也没有显示。
显示电影代码的主页:
主页.js
import React, { Component } from 'react';
import { StyleSheet, Platform, View, ActivityIndicator, FlatList, Text, Image, Alert, LayoutAnimation, YellowBox , Button , AsyncStorage } from 'react-native';
import Icon from 'react-native-vector-icons/FontAwesome';
export default class Home extends Component {
constructor(props) {
super(props);
this.state = {
UrlImage : '',
movie_desc : '',
favourite : false
};
}
GetItem (movie_description) {
Alert.alert(movie_description);
}
SaveData = async() =>
{
const movieData = {
UrlImage : this.state.UrlImage,
movie_desc : this.state.movie_desc
};
AsyncStorage.setItem('movie',JSON.stringify(movieData));
}
ShowMovies = () =>{
return fetch('https://uncoiled-crust.000webhostapp.com/api/movies_db.php')
.then((response) => response.json())
.then((responseJson) => {
const result = responseJson.map((value, index) => ({
...value,
isFavourite: 0
}))
this.setState({
isLoading: false,
dataSource: result
}, function() {
// In this block you can do something with new state.
});
})
.catch((error) => {
console.error(error);
});
}
componentWillMount()
{
const { movie_desc, UrlImage, favorite } = this.props;
this.setState({ movie_desc, UrlImage, favorite });
}
SelectItem(movie_desc){
Alert.alert(movie_desc);
}
componentWillUpdate() {
LayoutAnimation.easeInEaseOut();
}
componentDidMount(){
this.ShowMovies();
}
FlatListItemSeparator = () => {
return (
<View
style={{
height: .5,
width: "100%",
backgroundColor: "#000",
}}
/>
);
}
changeisFavorite = async (item, index) => {
let arr = [...this.state.dataSource]
arr[index].isFavorite = item.isFavorite == 1 ? 0:1;
this.setState({ dataSource: arr });
this.SaveData();
}
render()
{
const { movie_desc, UrlImage, favorite } = this.state;
return (
<View style={styles.MainContainer}>
<FlatList
data={ this.state.dataSource }
ItemSeparatorComponent = {this.FlatListItemSeparator}
renderItem={({item,index}) =>
<View style={{flex:1, flexDirection: 'row'}}>
<Icon
name={item.isFavorite == 1 ? 'heart' : 'heart-o'}
color={item.isFavorite == 1 ? '#F44336' : 'rgb(50, 50, 50)'}
size={30}
style={{ marginBottom: 10, marginTop: 20 }}
onPress={() => this.changeisFavorite(item, index)}
/>
<Image source = {{ uri: item.url_image}} style={styles.imageView} />
<Text style={styles.textView} >{item.movie_description}</Text>
</View>
}
/>
</View>
);
}
}
const styles = StyleSheet.create({
MainContainer :{
justifyContent: 'center',
flex:1,
margin: 5,
marginTop: (Platform.OS === 'ios') ? 20 : 0,
},
imageView: {
width: '50%',
height: 350 ,
margin: 7,
borderRadius : 7
},
textView: {
width:'50%',
textAlignVertical:'center',
padding:10,
color: '#000'
}
});
现在这是在 Flatlist 中显示电影的收藏夹区域
ShowFavorites.js
import React, { Component } from 'react';
import { StyleSheet, Platform, View, ActivityIndicator, FlatList, Text, Image, Alert, LayoutAnimation, YellowBox , Button , AsyncStorage } from 'react-native';
export default class Favourites extends Component {
constructor(props) {
super(props);
this.state = {
data : []
};
}
FlatListItemSeparator = () => {
return (
<View
style={{
height: .5,
width: "100%",
backgroundColor: "#000",
}}
/>
);
}
componentDidMount() {
AsyncStorage.getItem('movie').then(data => this.setState({ data }));
}
render() {
return (
<View styles={styles.MainContainer}>
<FlatList
data={ this.state.data }
ItemSeparatorComponent = {this.FlatListItemSeparator}
renderItem={({item}) =>
<View style={{flex:1, flexDirection: 'row'}}>
<Image source = {{ uri: item.url_image }} style={styles.imageView} />
<Text style={styles.textView} >{item.movie_description}</Text>
</View>
}
keyExtractor={(item, index) => index.toString()}
/>
</View>
);
}
}
const styles = StyleSheet.create({
MainContainer :{
justifyContent: 'center',
flex:1,
margin: 5,
marginTop: (Platform.OS === 'ios') ? 20 : 0,
},
imageView: {
width: '50%',
height: 100 ,
margin: 7,
borderRadius : 7
},
textView: {
width:'50%',
textAlignVertical:'center',
padding:10,
color: '#000'
}
});
有什么我做的不太正确吗?我需要在这里指出正确的方向。
编辑 现在我已经将代码编辑为看起来像这样,我得到这个错误:
source.uri should not be an empty string
我的Home.js和Showfavourites.js的代码看起来像这样
主页.js
import React, { Component } from 'react';
import { StyleSheet, Platform, View, ActivityIndicator, FlatList, Text, Image, Alert, LayoutAnimation, YellowBox , Button } from 'react-native';
import AsyncStorage from "@react-native-async-storage/async-storage";
import Icon from 'react-native-vector-icons/FontAwesome';
export default class Home extends Component {
constructor(props) {
super(props);
this.state = {
url_image : '',
movie_description : '',
favourite : false
};
}
GetItem (movie_description) {
Alert.alert(movie_description);
}
SaveData = async () =>
{
const movieData = {
UrlImage : this.state.url_image,
movie_desc : this.state.movie_description
};
await AsyncStorage.setItem('@movie',JSON.stringify(movieData));
}
ShowMovies = () =>{
return fetch('https://uncoiled-crust.000webhostapp.com/api/movies_db.php')
.then((response) => response.json())
.then((responseJson) => {
const result = responseJson.map((value, index) => ({
...value,
isFavourite: 0
}))
this.setState({
isLoading: false,
dataSource: result
}, function() {
// In this block you can do something with new state.
});
})
.catch((error) => {
console.error(error);
});
}
componentWillMount()
{
const { movie_description, url_image, favorite } = this.props;
this.setState({ movie_description, url_image, favorite });
}
SelectItem(movie_description){
Alert.alert(movie_description);
}
componentWillUpdate() {
LayoutAnimation.easeInEaseOut();
}
componentDidMount(){
this.ShowMovies();
}
FlatListItemSeparator = () => {
return (
<View
style={{
height: .5,
width: "100%",
backgroundColor: "#000",
}}
/>
);
}
changeisFavorite = async (item, index) => {
let arr = [...this.state.dataSource]
arr[index].isFavorite = item.isFavorite == 1 ? 0:1;
this.setState({ dataSource: arr });
this.SaveData();
}
render()
{
const { movie_description, url_image, favorite } = this.state;
return (
<View style={styles.MainContainer}>
<FlatList
data={ this.state.dataSource }
ItemSeparatorComponent = {this.FlatListItemSeparator}
renderItem={({item,index}) =>
<View style={{flex:1, flexDirection: 'row'}}>
<Icon
name={item.isFavorite == 1 ? 'heart' : 'heart-o'}
color={item.isFavorite == 1 ? '#F44336' : 'rgb(50, 50, 50)'}
size={30}
style={{ marginBottom: 10, marginTop: 20 }}
onPress={() => this.changeisFavorite(item, index)}
/>
<Image source = {{ uri: item.url_image}} style={styles.imageView} />
<Text style={styles.textView} >{item.movie_description}</Text>
</View>
}
/>
</View>
);
}
}
const styles = StyleSheet.create({
MainContainer :{
justifyContent: 'center',
flex:1,
margin: 5,
marginTop: (Platform.OS === 'ios') ? 20 : 0,
},
imageView: {
width: '50%',
height: 350 ,
margin: 7,
borderRadius : 7
},
textView: {
width:'50%',
textAlignVertical:'center',
padding:10,
color: '#000'
}
});
至于节目收藏夹它看起来像这样
import React, { Component } from 'react';
import { StyleSheet, Platform, View, ActivityIndicator, FlatList, Text, Image, Alert, LayoutAnimation, YellowBox , Button } from 'react-native';
import AsyncStorage from "@react-native-async-storage/async-storage";
export default class Favourites extends Component {
constructor(props) {
super(props);
this.state = {
data : [] ,
url_image : '' ,
movie_description : ''
};
}
FlatListItemSeparator = () => {
return (
<View
style={{
height: .5,
width: "100%",
backgroundColor: "#000",
}}
/>
);
}
componentDidMount() {
AsyncStorage.getItem('movie').then(data => this.setState({ data }));
}
render() {
return (
<View styles={styles.MainContainer}>
<FlatList
data={ this.state.data }
ItemSeparatorComponent = {this.FlatListItemSeparator}
renderItem={({item}) =>
<View style={{flex:1, flexDirection: 'row'}}>
<Image source = {{ uri: this.state.url_image }} style={styles.imageView} />
<Text style={styles.textView} >{this.state.movie_description}</Text>
</View>
}
keyExtractor={(item, index) => index.toString()}
/>
</View>
);
}
}
const styles = StyleSheet.create({
MainContainer :{
justifyContent: 'center',
flex:1,
margin: 5,
marginTop: (Platform.OS === 'ios') ? 20 : 0,
},
imageView: {
width: '50%',
height: 100 ,
margin: 7,
borderRadius : 7
},
textView: {
width:'50%',
textAlignVertical:'center',
padding:10,
color: '#000'
}
});
现在我得到这个:
source.uri cannot be an empty string
为什么会这样?
解决方案
根据代码观察,我可以看到您使用了 react-native 中的 AsyncStorage,它在很久以前被 react-native 弃用,因此使用异步存储来存储应用程序数据,而不是我们必须安装异步存储的 npm @react -native-async-storage/async-storage 包以使用异步存储功能。
并且代码还包含一些异步调用,而无需等待任务完成将导致意外。
所以尝试使用如下代码:
HomeScreen.js
import React, { Component } from 'react';
import { StyleSheet, Platform, View, ActivityIndicator, FlatList, Text, Image, Alert, LayoutAnimation, YellowBox , Button } from 'react-native';
import AsyncStorage from "@react-native-async-storage/async-storage";
import Icon from 'react-native-vector-icons/FontAwesome';
export default class Home extends Component {
constructor(props) {
super(props);
this.state = {
UrlImage : '',
movie_desc : '',
favourite : false
};
}
GetItem (movie_description) {
Alert.alert(movie_description);
}
SaveData = async () =>
{
const movieData = {
UrlImage : this.state.UrlImage,
movie_desc : this.state.movie_desc
};
await AsyncStorage.setItem('@movie',JSON.stringify(movieData));
}
ShowMovies = () =>{
return fetch('https://uncoiled-crust.000webhostapp.com/api/movies_db.php')
.then((response) => response.json())
.then((responseJson) => {
const result = responseJson.map((value, index) => ({
...value,
isFavourite: 0
}))
this.setState({
isLoading: false,
dataSource: result
}, function() {
// In this block you can do something with new state.
});
})
.catch((error) => {
console.error(error);
});
}
componentWillMount()
{
const { movie_desc, UrlImage, favorite } = this.props;
this.setState({ movie_desc, UrlImage, favorite });
}
SelectItem(movie_desc){
Alert.alert(movie_desc);
}
componentWillUpdate() {
LayoutAnimation.easeInEaseOut();
}
componentDidMount(){
this.ShowMovies();
}
FlatListItemSeparator = () => {
return (
<View
style={{
height: .5,
width: "100%",
backgroundColor: "#000",
}}
/>
);
}
changeisFavorite = async (item, index) => {
let arr = [...this.state.dataSource]
arr[index].isFavorite = item.isFavorite == 1 ? 0:1;
this.setState({ dataSource: arr });
this.SaveData();
}
render()
{
const { movie_desc, UrlImage, favorite } = this.state;
return (
<View style={styles.MainContainer}>
<FlatList
data={ this.state.dataSource }
ItemSeparatorComponent = {this.FlatListItemSeparator}
renderItem={({item,index}) =>
<View style={{flex:1, flexDirection: 'row'}}>
<Icon
name={item.isFavorite == 1 ? 'heart' : 'heart-o'}
color={item.isFavorite == 1 ? '#F44336' : 'rgb(50, 50, 50)'}
size={30}
style={{ marginBottom: 10, marginTop: 20 }}
onPress={() => this.changeisFavorite(item, index)}
/>
<Image source = {{ uri: item.url_image}} style={styles.imageView} />
<Text style={styles.textView} >{item.movie_description}</Text>
</View>
}
/>
</View>
);
}
}
const styles = StyleSheet.create({
MainContainer :{
justifyContent: 'center',
flex:1,
margin: 5,
marginTop: (Platform.OS === 'ios') ? 20 : 0,
},
imageView: {
width: '50%',
height: 350 ,
margin: 7,
borderRadius : 7
},
textView: {
width:'50%',
textAlignVertical:'center',
padding:10,
color: '#000'
}
});
ShowFavorites.js
import React, { Component } from 'react';
import { StyleSheet, Platform, View, ActivityIndicator, FlatList, Text, Image, Alert, LayoutAnimation, YellowBox , Button } from 'react-native';
import AsyncStorage from "@react-native-async-storage/async-storage";
export default class Favourites extends Component {
constructor(props) {
super(props);
this.state = {
data : []
};
}
FlatListItemSeparator = () => {
return (
<View
style={{
height: .5,
width: "100%",
backgroundColor: "#000",
}}
/>
);
}
componentDidMount() {
AsyncStorage.getItem('movie').then(data => this.setState({ data }));
}
render() {
return (
<View styles={styles.MainContainer}>
<FlatList
data={ this.state.data }
ItemSeparatorComponent = {this.FlatListItemSeparator}
renderItem={({item}) =>
<View style={{flex:1, flexDirection: 'row'}}>
<Image source = {{ uri: item.url_image }} style={styles.imageView} />
<Text style={styles.textView} >{item.movie_description}</Text>
</View>
}
keyExtractor={(item, index) => index.toString()}
/>
</View>
);
}
}
const styles = StyleSheet.create({
MainContainer :{
justifyContent: 'center',
flex:1,
margin: 5,
marginTop: (Platform.OS === 'ios') ? 20 : 0,
},
imageView: {
width: '50%',
height: 100 ,
margin: 7,
borderRadius : 7
},
textView: {
width:'50%',
textAlignVertical:'center',
padding:10,
color: '#000'
}
});
推荐阅读
- android - 无法从网络安全配置 XML 中引用原始资源
- hyperledger-fabric - 当 peer admin 无权写入 orderer 时,如何创建通道?
- ajax - 来自 GIPHY API 上的异步回调的未定义响应
- kendo-ui - 为什么我的 Kendo ListBox TransferAll 不起作用
- django - 如何使用 django send_mail() 将电子邮件放入已发送文件夹?
- wpf - 成员“IsChecked”无法识别或无法访问。谁能帮我解决这个问题
- reactjs - 如何返回具有递增或递减值的 redux 状态?
- php - xhttp.send() 命令,“被 CORS 策略阻止:仅支持跨源请求......”等
- php - 将 Strtotime('now') 拆分为秒和分钟
- gnuplot - 与 gnuplot 格式说明符 %t 和 %T 不一致?