Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
287 views
in Technique[技术] by (71.8m points)

react native - How do I use Asyncstorage to save and view JSON Data on second screen?

I have some code that does not work as i expect, when i click the favorite icon, its supposed to save to async Storage. The code works to select the movies from the flatlist, where i have the problem is saving it to asyncStorage and then when i click the page to display the selected favorite movie in a flat list nothing shows up.

The homepage to show the movies code :

Home.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'
     
    }
    });

Now this is the Favorites Area to display the movies in 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'
  }
  });

Is there something I am not doing very correctly? I need to be point in the right direction here.

Edits Now I have edited the code to Look like this , and I am getting this as Error :

source.uri should not be an empty string

My Code for both the Home.js and Showfavourites.js Looks like this

Home.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'
 
   }
 });

As for the show Favourites it Looks Like this

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: {

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

As per the code observation, I can see you have used AsyncStorage from react-native which is deprecated by react-native a long time ago so to use the async storage to store app data than we have to install the npm of async storage @react-native-async-storage/async-storage package to use async storage features.

and the code also contains some async call without the wait to finish of the task will result unexpected.

so try to use code as below:

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'
  }
});

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...