首页 > 解决方案 > 如何使用 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.jsShowfavourites.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-nativeasyncstorage

解决方案


根据代码观察,我可以看到您使用了 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'
  }
});

推荐阅读