Storing application data

Now, let's shift our attention to storing data within a React Native application. The AsyncStorage API works the same on both iOS and Android platforms. You would use this API for applications that don't require any network connectivity in the first place, or to store data that's eventually synchronized using an API endpoint once a network becomes available.

Let's look at some code that allows the user to enter a key and a value, and then stores them:

import React, { Component } from 'react'; 
import { 
  AppRegistry, 
  Text, 
  TextInput, 
  View, 
  ListView, 
  AsyncStorage, 
} from 'react-native'; 
import { fromJS } from 'immutable'; 
 
import styles from './styles'; 
import Button from './Button'; 
 
class StoringData extends Component { 
 
  // The initial state of this component 
  // consists of the current "key" and "value" 
  // that the user is entering. It also has 
  // a "source" for the list view to display 
  // everything that's been stored. 
  state = { 
    data: fromJS({ 
      key: null, 
      value: null, 
      source: new ListView.DataSource({ 
        rowHasChanged: (r1, r2) => r1 !== r2, 
      }), 
    }), 
  } 
 
  // Getter for "Immutable.js" state data... 
  get data() { 
    return this.state.data; 
  } 
 
  // Setter for "Immutable.js" state data... 
  set data(data) { 
    this.setState({ data }); 
  } 
 
  // Uses "AsyncStorage.setItem()" to store 
  // the current "key" and "value" states. 
  // When this completes, we can delete 
  // "key" and "value" and reload the item list. 
  setItem = () => 
    AsyncStorage 
      .setItem( 
        this.data.get('key'), 
        this.data.get('value') 
      ) 
      .then(() => { 
        this.data = this.data 
          .delete('key') 
          .delete('value'); 
      }) 
      .then(() => this.loadItems()) 
 
  // Uses "AsyncStorage.clear()" to empty any stored 
  // values. Then, it loads the empty list of 
  // items to clear the item list on the screen. 
  clearItems = () => 
    AsyncStorage 
      .clear() 
      .then(() => this.loadItems()) 
 
  // This method is async because awaits on the 
  // data store keys and values, which are two 
  // dependent async calls. 
  async loadItems() { 
    const keys = await AsyncStorage.getAllKeys(); 
    const values = await AsyncStorage.multiGet(keys); 
 
    this.data = this.data 
      .update( 
        'source', 
        source => source.cloneWithRows(values) 
      ); 
  } 
 
  // Load any existing items that have 
  // already been stored when the app starts. 
  componentWillMount() { 
    this.loadItems(); 
  } 
 
  render() { 
    // The methods that we need... 
    const { 
      setItem, 
      clearItems, 
    } = this; 
 
    // The state that we need... 
    const { 
      source, 
      key, 
      value, 
    } = this.data.toJS(); 
 
    return ( 
      <View style={styles.container}> 
        <Text>Key:</Text> 
        <TextInput 
          style={styles.input} 
          value={key} 
          onChangeText={(v) => { 
            this.data = this.data.set('key', v); 
          }} 
        /> 
        <Text>Value:</Text> 
        <TextInput 
          style={styles.input} 
          value={value} 
          onChangeText={(v) => { 
            this.data = this.data.set('value', v); 
          }} 
        /> 
        <View style={styles.controls}> 
          <Button 
            label="Add" 
            onPress={setItem} 
          /> 
          <Button 
            label="Clear" 
            onPress={clearItems} 
          /> 
        </View> 
        <View style={styles.list}> 
          <ListView 
            enableEmptySections 
            dataSource={source} 
            renderRow={([k, v]) => ( 
              <Text>{v} ({k})</Text> 
            )} 
          /> 
        </View> 
      </View> 
    ); 
  } 
} 
 
AppRegistry.registerComponent( 
  'StoringData', 
  () => StoringData 
); 

Before we walk through what this code is doing, let's first take a look at the screen, since it'll provide most of the explanation for me:

Storing application data

As you can see, there are two input fields and two buttons. The fields allow the user to enter a new key and value. The Add button allows the user to store this key-value pair locally on their device, while the Clear button clears any existing items that have been stored previously.

The AsyncStorage API works the same for both iOS and Android. Under the hood, AsyncStorage works very differently depending on which platform it's running on. The reason React Native is able to expose the same storage API on both platforms is due to its simplicity—it's just simple key-value pairs. Anything more complex than that is left up to the application developer.

The abstractions that we've created around AsyncStorage in this example are simple. The idea is to simply set and get items. However, even simple things like this warrant a little abstraction. For example, the setItem() method we've implemented here will make the asynchronous call to AsyncStorage and update the items state once that has completed. Loading items is even more complicated because we need to get the keys and values as two separate asynchronous operations.

So, you might be wondering, why the need for all the asynchronicity for simple storage calls? The main reason is to keep the UI responsive. If there are pending screen repaints that need to happen while data is being written to disk, preventing those from happening by blocking them would lead to a sub-optimal user experience.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.118.1.158